Jump to content

Footstep sound in c++


cassius
 Share

Recommended Posts

I have set up the footstep sound for when player moves, but it sounds more like a machine gun . How can I slow it down to walking pace.

 

EDIT: is this something to do with SetLoopMode?

amd quad core 4 ghz / geforce 660 ti 2gb / win 10

Blender,gimp,silo2,ac3d,,audacity,Hexagon / using c++

Link to comment
Share on other sites

There's a few ways to do this.

 

The best way I think,

Using Time::GetCurrent(), and checking if X amount of time has passed to call Sound::Play() or Source::Play(). You'd also want to check to see if the audio isn't playing.

 

This is the best way as you can add velocity in with your sounds. For example, if the player is running, the footsteps would be faster.

 

The second way, and by far the easiest, add the time delay in your audio file. With SetLoopMode(true). The audio file will play a walking sound until you call Pause(), or Stop()

Link to comment
Share on other sites

The 3rd way is to set a hook function for your animations. Allow the function to be called at any special frames you wish. Then setup this function to be called at the frames that best match when the feet are on the ground. Then inside this function play your footstep sound. This adjusts automatically with your animation speed too!

  • Upvote 2
Link to comment
Share on other sites

I have changed my mind about having footstep sounds. My character is walking on soft grass anyway so footsteps would not be audible., but I need to get rid of the gliding effect as the character walks. A slight movement of the gun arms might be enough.What do you think?

amd quad core 4 ghz / geforce 660 ti 2gb / win 10

Blender,gimp,silo2,ac3d,,audacity,Hexagon / using c++

Link to comment
Share on other sites

@gamecreator

 

Note that I did this in lua but a similar thing could be done if needed in C++. I reuse this idea for 1 time animations and continuous animations. For continuous if you specify a special frame callback it'll get called every frame and then you can do the work in there.

 

All the work is done in AnimationManager.lua Below is the entire code for that:

 

--[[
This script provides a programming interface to easily manage animation transitions.
Just call the SetAnimationSequence() function from any other script and the entity's animation
will be automatically blended from the previous sequence.  It's okay to call this repeatedly with
the same sequence.  A new sequence will only be added in the animation stack when it is different 
from the previous sequence.
]]--
if AnimationManager~=nil then return end

AnimationManager={}

function AnimationManager:Create(entity)
if entity==nil then Debug:Error("Entity cannot be nil.") end
local animationmanager = {}
animationmanager.entity = entity
animationmanager.animations={}
animationmanager.frameoffset = math.random(0,1000)
local k,v
for k,v in pairs(AnimationManager) do
animationmanager[k] = v
end
return animationmanager
end

function AnimationManager:SetAnimationSequence(sequence, speed, blendtime, mode, endHookScript, endHook, specialFrameHook, specialFrame, endFrame)

--Handle default parameters
if speed==nil then speed=1.0 end
if blendtime==nil then blendtime=500 end
if  mode==nil then mode=0 end

--Check for redundant animation descriptor
if mode==0 then
if #self.animations>0 then
if self.animations[#self.animations].sequence==sequence then
if self.animations[#self.animations].speed==speed then
--No change to blend time, so don't alter this?
self.animations[#self.animations].blendtime=blendtime
return
end
end
end
end

--Create new animation descriptor and add to animation stack
local animation={}
animation.blendstart=Time:GetCurrent()
animation.blendfinish=animation.blendstart+blendtime
animation.sequence=sequence
animation.speed=speed
animation.mode=mode
animation.starttime=animation.blendstart
animation.endHookScript=endHookScript
animation.endHook=endHook
animation.endOfSequenceReached=false
animation.endFrame = endFrame
animation.specialFrameHook = specialFrameHook
animation.specialFrame = specialFrame

--Add a random offset to looped animations so they're not all identical
--if mode==0 then
-- animation.frameoffset = math.random(0,(self.entity:GetAnimationLength(sequence)))
--end

table.insert(self.animations,animation)
end

function AnimationManager:ClearAnimations()
self.animations = {}
end

--[[
function Script:GetFrame(seq)
local i,animation
currenttime=Time:GetCurrent()

       for i,animation in ipairs(self.animations) do
if animation.sequence == seq then
return (currenttime-animation.blendstart) * animation.speed
end
end

return -1 
end
]]--

function AnimationManager:Update()
local i,animation,blend,frame,n,completedanimation
local doanimation=false
local currenttime=Time:GetCurrent()
local maxanim=-1

for i,animation in ipairs(self.animations) do

--Lock the matrix before the first sequence is applied
if doanimation==false then
doanimation=true
self.entity:LockMatrix()
end

--Calculate blend value
blend = (currenttime-animation.blendstart)/(animation.blendfinish-animation.blendstart)
blend = math.min(1.0,blend) 

if animation.mode==0 then
frame = currenttime * animation.speed + self.frameoffset--animation.frameoffset
local length = self.entity:GetAnimationLength(animation.sequence,true)
if animation.specialFrameHook ~= nil then
animation.specialFrameHook(animation.endHookScript, animation.sequence, frame, length)
end
else
frame = (currenttime-animation.blendstart) * animation.speed
local length = self.entity:GetAnimationLength(animation.sequence,true)

-- trigger when special frame is hit
if animation.specialFrame ~= nil then
if frame > animation.specialFrame then
animation.specialFrameHook(animation.endHookScript, animation.sequence)
animation.specialFrame = nil
end
end

--If a certain frame was specified, call the hook early and remove it
--[[
if animation.endFrame~=nil then
if frame>animation.endFrame then
animation.endHook(animation.endHookScript, animation.sequence)
animation.endFrame=nil
animation.endHook=nil
animation.endHookScript=nil
end
end
]]

if frame>=length-1 then
frame=length-1
maxanim = i+1--clears all animations up to this one, and then this one
if (not animation.endOfSequenceReached) then
animation.endOfSequenceReached=true
if animation.endHookScript then
if animation.endHook then
animation.endHook(animation.endHookScript, animation.sequence)
end
end
end
end
end

--Apply the animation
self.entity:SetAnimationFrame(frame, blend, animation.sequence, true)

--If this animation is blended in 100%, all previous looping animation sequences can be dropped
if blend>=1.0 then
maxanim = math.max(maxanim,i)
end

end

--Unlock entity matrix if any animations were applied
if doanimation==true then
self.entity:UnlockMatrix()
end

--Clear blended out animation - moved this out of the loop to prevent jittering
if maxanim>-1 then
local index=1
for n,completedanimation in ipairs(self.animations) do
if n<maxanim then
if completedanimation.mode==0 or completedanimation.endOfSequenceReached==true then
table.remove(self.animations,index)
else
index=index+1
end
else
break
end
end
end

end

function AnimationManager:GetAnimationStackSize()
return #self.animations
end

 

Usage is:

 

self.animMgr:SetAnimationSequence("Chop1", 0.04, 250, 1, self, self.EndAction, self.SpecialFrame, 14)

function Script:SpecialFrame(seq)
-- look into: I don't think I need to call the Use() of the current object each time
if seq == "Chop1" then
local sound = Math:Round(math.random(1, 4))
self.sounds.chop[sound]:Play()
self.currentObject.script:Use(self.equippedItem)
end
end

 

For walking, if anyone cares, I use the same AnimationManager.lua above but this is the callback that gets called each frame of the animation. Inside I check the frames (8 and 19 in this case which are the frames where the feet are hitting the ground) and toggle a left/right. This will sync up the footsteps sound.

 

 

 

function Script:OnAnimationFrame(seq, frame, length)

if seq == "Walk" then

if math.floor(frame % length) == 8 and self.leftFoot == false then

local sound = Math:Round(math.random(1, 5))

self.sounds.walk[sound]:Play()

self.leftFoot = true

end

 

if math.floor(frame % length) == 19 and self.rightFoot == false then

local sound = Math:Round(math.random(1, 5))

self.sounds.walk[sound]:Play()

self.rightFoot = true

end

 

-- reset

if math.floor(frame % length) == 0 then

self.leftFoot = false

self.rightFoot = false

end

end

end[/code]

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...