feature/audioengine #26
BIN
assets/audio/music/level1/bass/bass.ogg
Normal file
BIN
assets/audio/music/level1/bass/bass.ogg
Normal file
Binary file not shown.
BIN
assets/audio/music/level1/battle.ogg
Normal file
BIN
assets/audio/music/level1/battle.ogg
Normal file
Binary file not shown.
BIN
assets/audio/music/level1/choral.ogg
Normal file
BIN
assets/audio/music/level1/choral.ogg
Normal file
Binary file not shown.
BIN
assets/audio/music/level1/drums.ogg
Normal file
BIN
assets/audio/music/level1/drums.ogg
Normal file
Binary file not shown.
BIN
assets/audio/music/level1/flute.ogg
Normal file
BIN
assets/audio/music/level1/flute.ogg
Normal file
Binary file not shown.
BIN
assets/audio/music/level1/guitar.ogg
Normal file
BIN
assets/audio/music/level1/guitar.ogg
Normal file
Binary file not shown.
BIN
assets/audio/music/level1/violin.ogg
Normal file
BIN
assets/audio/music/level1/violin.ogg
Normal file
Binary file not shown.
BIN
assets/audio/sounds/hurt.ogg
Normal file
BIN
assets/audio/sounds/hurt.ogg
Normal file
Binary file not shown.
91
lib/audio.lua
Normal file
91
lib/audio.lua
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
local ease = require "lib.utils.easing"
|
||||||
|
local AnimationNode = require "lib.animation_node"
|
||||||
|
|
||||||
|
--- @alias SourceFilter { type: "bandpass"|"highpass"|"lowpass", volume: number, highgain: number, lowgain: number }
|
||||||
|
|
||||||
|
--- @class Audio
|
||||||
|
--- @field musicVolume number
|
||||||
|
--- @field soundVolume number
|
||||||
|
--- @field looped boolean
|
||||||
|
--- @field animationNode AnimationNode?
|
||||||
|
--- @field from love.Source?
|
||||||
|
--- @field to love.Source?
|
||||||
|
audio = {}
|
||||||
|
audio.__index = audio
|
||||||
|
|
||||||
|
--- здесь мы должны выгружать значения из файлика с сохранением настроек
|
||||||
|
local function new(musicVolume, soundVolume)
|
||||||
|
return setmetatable({
|
||||||
|
musicVolume = musicVolume,
|
||||||
|
soundVolume = soundVolume,
|
||||||
|
looped = true
|
||||||
|
}, audio)
|
||||||
|
end
|
||||||
|
|
||||||
|
function audio:update(dt)
|
||||||
|
if self.animationNode and self.animationNode.state == "running" then
|
||||||
|
self.animationNode:update(dt)
|
||||||
|
self.from:setVolume(self.musicVolume - self.animationNode:getValue() * self.musicVolume)
|
||||||
|
self.to:setVolume(self.animationNode:getValue() * self.musicVolume)
|
||||||
|
-- print(self.animationNode.t)
|
||||||
|
elseif self.animationNode and self.animationNode.state == "finished" then
|
||||||
|
self.from:stop()
|
||||||
|
self.animationNode:finish()
|
||||||
|
self.animationNode = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- if from is nil, than we have fade in to;
|
||||||
|
--- if to is nil, than we have fade out from
|
||||||
|
---
|
||||||
|
--- also we should guarantee, that from and to have the same volume
|
||||||
|
--- @param from love.Source
|
||||||
|
--- @param to love.Source
|
||||||
|
--- @param ms number? in milliseconds
|
||||||
|
function audio:crossfade(from, to, ms)
|
||||||
|
print("[Audio]: Triggered crossfade")
|
||||||
|
self:play(to)
|
||||||
|
to:setVolume(0)
|
||||||
|
self.from = from
|
||||||
|
self.to = to
|
||||||
|
self.animationNode = AnimationNode {
|
||||||
|
function(node) end,
|
||||||
|
onEnd = function()
|
||||||
|
self.from:setVolume(0)
|
||||||
|
self.to:setVolume(self.musicVolume)
|
||||||
|
print("[Audio]: Crossfade done")
|
||||||
|
end,
|
||||||
|
duration = ms or 1000,
|
||||||
|
easing = ease.easeOutCubic,
|
||||||
|
}
|
||||||
|
self.animationNode:run()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param source love.Source
|
||||||
|
--- @param settings SourceFilter?
|
||||||
|
--- @param effectName string?
|
||||||
|
function audio:play(source, settings, effectName)
|
||||||
|
if settings then
|
||||||
|
source:setFilter(settings)
|
||||||
|
end
|
||||||
|
if effectName then
|
||||||
|
source:setEffect(effectName, true)
|
||||||
|
end
|
||||||
|
if source:getType() == "stream" then
|
||||||
|
source:setLooping(self.looped)
|
||||||
|
source:setVolume(self.musicVolume)
|
||||||
|
return source:play()
|
||||||
|
end
|
||||||
|
source:setVolume(self.soundVolume)
|
||||||
|
return source:play()
|
||||||
|
end
|
||||||
|
|
||||||
|
function audio:setMusicVolume(volume)
|
||||||
|
self.musicVolume = volume
|
||||||
|
end
|
||||||
|
|
||||||
|
function audio:setSoundVolume(volume)
|
||||||
|
self.soundVolume = volume
|
||||||
|
end
|
||||||
|
|
||||||
|
return { new = new }
|
||||||
@ -18,6 +18,9 @@ local path = nil
|
|||||||
local function new(type, template)
|
local function new(type, template)
|
||||||
local size = Vec3 { 30, 30 } -- magic numbers for testing purposes only
|
local size = Vec3 { 30, 30 } -- magic numbers for testing purposes only
|
||||||
print(type, template, size)
|
print(type, template, size)
|
||||||
|
|
||||||
|
Tree.audio:play(Tree.assets.files.audio.music.level1.battle)
|
||||||
|
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
size = size,
|
size = size,
|
||||||
characters = {},
|
characters = {},
|
||||||
|
|||||||
52
lib/music.lua
Normal file
52
lib/music.lua
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
-- --- @class Music
|
||||||
|
-- --- @field source table<string, love.Source> audio streams, that supports multitrack (kind of)
|
||||||
|
-- --- @field offset number
|
||||||
|
-- music = {}
|
||||||
|
-- music.__index = music
|
||||||
|
|
||||||
|
-- --- @param path string accepts path to dir with some music files (example: "main_ambient"; "player/theme1" and etc etc)
|
||||||
|
-- local function new(path)
|
||||||
|
-- local dir = Tree.assets.files.audio.music[path]
|
||||||
|
-- --- @type table<string, love.Source>
|
||||||
|
-- local source = {}
|
||||||
|
-- print(dir)
|
||||||
|
|
||||||
|
-- for _, v in pairs(dir) do
|
||||||
|
-- print(v.filename)
|
||||||
|
-- source[v.filename] = v.source
|
||||||
|
-- print(v.filename)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- print('[music]: new source: ', table.concat(source, ' '))
|
||||||
|
|
||||||
|
-- return setmetatable({ source = source, offset = 0 }, music)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function music:update()
|
||||||
|
-- for _, v in ipairs(self.source) do
|
||||||
|
-- v:seek()
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- --- pause stemfile or music at all
|
||||||
|
-- --- @param filename? string
|
||||||
|
-- function music:pause(filename)
|
||||||
|
-- if filename then
|
||||||
|
-- self.source[filename]:pause()
|
||||||
|
-- else
|
||||||
|
-- for _, v in pairs(self.source) do
|
||||||
|
-- v:pause()
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- --- play music stemfile by his name
|
||||||
|
-- --- @param filename string
|
||||||
|
-- --- @return boolean
|
||||||
|
-- function music:play(filename)
|
||||||
|
-- print('[music]: ', table.concat(self.source, ' '))
|
||||||
|
-- self.source[filename]:seek(self.offset, "seconds")
|
||||||
|
-- return self.source[filename]:play()
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- return { new = new }
|
||||||
9
lib/sound.lua
Normal file
9
lib/sound.lua
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-- --- @class Sound
|
||||||
|
-- --- @field source love.Source just a sound
|
||||||
|
-- sound = {}
|
||||||
|
|
||||||
|
-- local function new()
|
||||||
|
-- return setmetatable({}, sound)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- return { new }
|
||||||
@ -51,7 +51,9 @@ function walk:cast(caster, target)
|
|||||||
local sprite = caster:has(Tree.behaviors.sprite)
|
local sprite = caster:has(Tree.behaviors.sprite)
|
||||||
if not sprite then return true end
|
if not sprite then return true end
|
||||||
AnimationNode {
|
AnimationNode {
|
||||||
function(node) caster:has(Tree.behaviors.map):followPath(path, node) end,
|
function(node)
|
||||||
|
caster:has(Tree.behaviors.map):followPath(path, node)
|
||||||
|
end,
|
||||||
onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end,
|
onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end,
|
||||||
}:run()
|
}:run()
|
||||||
|
|
||||||
@ -88,7 +90,10 @@ function regenerateMana:cast(caster, target)
|
|||||||
if not sprite then return true end
|
if not sprite then return true end
|
||||||
AnimationNode {
|
AnimationNode {
|
||||||
function(node)
|
function(node)
|
||||||
|
local audioPath = Tree.assets.files.audio
|
||||||
sprite:animate("hurt", node)
|
sprite:animate("hurt", node)
|
||||||
|
Tree.audio:crossfade(audioPath.music.level1.battle,
|
||||||
|
audioPath.music.level1.choral, 5000)
|
||||||
end,
|
end,
|
||||||
onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end
|
onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end
|
||||||
}:run()
|
}:run()
|
||||||
@ -141,7 +146,16 @@ function attack:cast(caster, target)
|
|||||||
children = {
|
children = {
|
||||||
AnimationNode {
|
AnimationNode {
|
||||||
function(node)
|
function(node)
|
||||||
|
local audioPath = Tree.assets.files.audio
|
||||||
targetSprite:animate("hurt", node)
|
targetSprite:animate("hurt", node)
|
||||||
|
--- @type SourceFilter
|
||||||
|
local settings = {
|
||||||
|
type = "bandpass",
|
||||||
|
volume = 1,
|
||||||
|
highgain = 0.1,
|
||||||
|
lowgain = 0.1
|
||||||
|
}
|
||||||
|
Tree.audio:play(audioPath.sounds.hurt, settings)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,11 @@ Tree = {
|
|||||||
Tree.fonts = (require "lib.utils.font_manager"):load("WDXL_Lubrifont_TC"):loadTheme("Roboto_Mono") -- дефолтный шрифт
|
Tree.fonts = (require "lib.utils.font_manager"):load("WDXL_Lubrifont_TC"):loadTheme("Roboto_Mono") -- дефолтный шрифт
|
||||||
Tree.panning = require "lib/panning"
|
Tree.panning = require "lib/panning"
|
||||||
Tree.controls = require "lib.controls"
|
Tree.controls = require "lib.controls"
|
||||||
|
Tree.audio = (require "lib.audio").new(1, 1)
|
||||||
Tree.level = (require "lib.level.level").new("procedural", "flower_plains") -- для теста у нас только один уровень, который сразу же загружен
|
Tree.level = (require "lib.level.level").new("procedural", "flower_plains") -- для теста у нас только один уровень, который сразу же загружен
|
||||||
|
|
||||||
Tree.behaviors = (require "lib.utils.behavior_loader")("lib/character/behaviors") --- @todo написать нормальную загрузку поведений
|
Tree.behaviors = (require "lib.utils.behavior_loader")("lib/character/behaviors") --- @todo написать нормальную загрузку поведений
|
||||||
|
-- Tree.audio = (require "lib.audio").new(1, 1)
|
||||||
-- Tree.behaviors.map = require "lib.character.behaviors.map"
|
-- Tree.behaviors.map = require "lib.character.behaviors.map"
|
||||||
-- Tree.behaviors.spellcaster = require "lib.character.behaviors.spellcaster"
|
-- Tree.behaviors.spellcaster = require "lib.character.behaviors.spellcaster"
|
||||||
-- Tree.behaviors.sprite = require "lib.character.behaviors.sprite"
|
-- Tree.behaviors.sprite = require "lib.character.behaviors.sprite"
|
||||||
|
|||||||
@ -50,6 +50,10 @@ function AssetBundle.loadFile(path)
|
|||||||
return love.graphics.newShader(path);
|
return love.graphics.newShader(path);
|
||||||
elseif (ext == "lua") then
|
elseif (ext == "lua") then
|
||||||
return require(string.gsub(path, ".lua", ""))
|
return require(string.gsub(path, ".lua", ""))
|
||||||
|
elseif (ext == "ogg") and string.find(path, "sounds") then
|
||||||
|
return love.audio.newSource(path, 'static')
|
||||||
|
elseif (ext == "ogg") and string.find(path, "music") then
|
||||||
|
return love.audio.newSource(path, 'stream')
|
||||||
end
|
end
|
||||||
return filedata
|
return filedata
|
||||||
end
|
end
|
||||||
|
|||||||
6
main.lua
6
main.lua
@ -18,7 +18,10 @@ function love.load()
|
|||||||
end
|
end
|
||||||
Tree.level.turnOrder:endRound()
|
Tree.level.turnOrder:endRound()
|
||||||
print("Now playing:", Tree.level.turnOrder.current)
|
print("Now playing:", Tree.level.turnOrder.current)
|
||||||
love.window.setMode(1280, 720, { resizable = true, msaa = 4, vsync = true })
|
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
|
||||||
|
|
||||||
|
-- Level1_music = (require "lib.music").new("level1/bass")
|
||||||
|
-- Level1_music:play("bass")
|
||||||
end
|
end
|
||||||
|
|
||||||
local lt = "0"
|
local lt = "0"
|
||||||
@ -29,6 +32,7 @@ function love.update(dt)
|
|||||||
testLayout:update(dt) -- потом UI, потому что нужно перехватить жесты и не пустить их дальше
|
testLayout:update(dt) -- потом UI, потому что нужно перехватить жесты и не пустить их дальше
|
||||||
Tree.panning:update(dt)
|
Tree.panning:update(dt)
|
||||||
Tree.level:update(dt)
|
Tree.level:update(dt)
|
||||||
|
Tree.audio:update(dt)
|
||||||
|
|
||||||
Tree.controls:cache()
|
Tree.controls:cache()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user