Footstep sound on different material

Blitz3D Forums/Blitz3D Programming/Footstep sound on different material

Mathieu A(Posted 2004) [#1]
Hi, I'd like to know how we can create footstep sound on different material. For exemple, when I walk into the sand it's not the same sound that when I walk on metal.

THX


Jim Teeuwen(Posted 2004) [#2]
pseudo code:

Select( Entity_that_Player_is_walking_on )
Case Wood: PlaySound( "footstep_wood" )
Case Iron: PlaySound( "footstep_iron" )
Case Sand: PlaySound( "footstep_sand" )
Case Snow: PlaySound( "footstep_snow" )
End Select


eBusiness(Posted 2004) [#3]
And so of course you would need to "mark" each entity with a material type.

Alternately you could use a "floortype"-map, I use such one in my Lousy Racing Game, feel free to take a look.


Jeroen(Posted 2004) [#4]
check the other thread somewhere on this forum regarding footsteps on different textures.


Mathieu A(Posted 2004) [#5]
Ok but what is the command to know wich material the player is walking on?


Zethrax(Posted 2004) [#6]
Yes, Halo posted some great footsteps sounds in the thread listed below:-

http://www.blitzbasic.com/Community/posts.php?topic=29552

To find out which material the player is walking on you first need to get the handle of the entity your player is colliding with, using 'CollisionEntity'. You can then get the entity's collision type by using 'GetEntityType', and use the number you've assigned as that entity's collision type to index arrays you've set up that contain the properties info for that entity-type.

Another way to do it is to use the 'NameEntity' command to store an array index to your entity's properties info in its namestring, and then use 'EntityName$ ( entity )' to retrieve the index when you collide with the entity.

You can also store custom Type pointer values in the namestring by converting the pointer value to and from an integer number using a couple of unofficial, undocumented commands called 'Handle()' and 'Object()'. You can find out more about these in the 'Undocumented' section at www.Blitzcoder.com .

Basically use:-

int_variable% = Handle( my_type_pointer.my_type )

to get the pointer value, and:-

my_type_pointer.my_type = Object.my_type( int_variable% )

to convert it back to a custom type pointer. The Object command needs to be followed by the custom type extension (in this case, .my_type) so it knows which custom data type to convert the number to.


bradford6(Posted 2004) [#7]
look at the getsurface,getbrush, get texture type commands i think they will give you what you are looking for

What I would do:
1. do a line pick every 5 cycles straight down from the players position
2. do a get brush to determine what material is applied to that surface
3. play corresponding sound during the walk sequence


Mathieu A(Posted 2004) [#8]
Thank you very much for all your advices


Techlord(Posted 2004) [#9]
wesh,

Another approach could be to put a simple switch trigger at the room/area entry point that changes the walking sound. However, this method is not suitable for large outdoor areas.

IMHO, Axeman's technique could be the simplest and most flexible. My version of the technique would go like so:
Collisions player,wood,method,response
Collisions player,sand,method,response
Collisions player,iron,method,response
Collisions player,snow,method,response
To detect and play sound dependent on surface
If EntityCollided(player,wood) PlaySound( "footstep_wood" )



jfk EO-11110(Posted 2004) [#10]
If for some reason the diffrent materials are all diffrent surfaces of the same mesh, you can use the new getbrush, gettexture and gettexturename$ functions (since blitz V.1.85), but bare in mind that getbrush and gettexture will create a brush and a texture copy in memory that have to be deleted after investigation, so it's a good idea to store all surface handles in arrays together with their sound handle only once right after loading. you can then parse a
that small array in the game loop and compare the stored Surface handles with PickedSurface() (from what bradford6 said)


Mathieu A(Posted 2004) [#11]
ok infortunelly, I 'got one mesh with one surface! I 'd like to know how to separate my mesh with several surface! But thank you for your advices!


jfk EO-11110(Posted 2004) [#12]
If a mesh is using diffrent textures, these textures will be the surfaces in blitz. there are several apps which let you assign multiple textures or materials to a mesh or to parts of the mesh. what App did you use to make your mesh?


Mathieu A(Posted 2004) [#13]
3DSMAx and I use the B3D pipeline exporter. In fact, I like to have access to all the different ground entity to make my footstep.


jfk EO-11110(Posted 2004) [#14]
If you have multiple textures in that mesh, it should also have multiple sufaces in Blitz. I am not shure how B3D Pipeline exports the Mesh. But with the method I described you can have diffrent footsteps with every texture. eg: grass.bmp uses grass.wav, wood.bmp uses wood.wav etc.

If your mesh has multiple texture files, it also has multiple surfaces - as long as you use LoadMesh to load it, and not LoadAnimMesh.


Mathieu A(Posted 2004) [#15]
In fact, my level is one mesh called "LEVEL.B3D" which contains differents entities (ground, wall, roof, etc..). My problem is that when I used the function Linepick to know what is the entities under the feet of the player, blitz return the global mesh (i.e "LEVEL").
So I'd like to know, if I must do a FindChildren() of my global level mesh or does it's possible (with B3D pipeline extension or in blitzcode) To have acces of all the entities which are pickable.

I hope that you understand what I said, my english wasn't perfect!!!


Mathieu A(Posted 2004) [#16]
I don't understand because when I 've made a "CountChildren(level)". It returns me 0. In fact, my level has no children. Why?


PowerPC603(Posted 2004) [#17]
That's because you used LoadMesh("Level.b3d").

Using LoadMesh, Blitz3D makes the entire level to be one mesh, without keeping the level's structure (so there aren't any children).

Use LoadAnimMesh instead, if you plan to use any commands for identifying children.


Mathieu A(Posted 2004) [#18]
yes, I discovered that but now It's very very slow! I've got 12000 polys but lots of children. Is that normal?


jfk EO-11110(Posted 2004) [#19]
Wesh - no need for loadanimmesh for static Meshes, just a waste of speed. So better use LoadMesh. yes, Linepick wil return the global mesh handle, but don't care! Simply use the PickedSurface() Command to find out what texture your player stepped on.

As I said, after loading the level you need to store all surfaces in an array. parallely you should store the used texture per surface. this way you can assign a sound to each surface. The reason why is the order of the surfaces of a mesh is never the same after loading - i mean, each time oyu load a mesh with multiple surfaces, the order of the surfaces is randomly diffrent. This might be a DirectX issue, however.

SO first parse all surfaces and store their handles in a array, you could also use a type, but imho tere is no need for slower types in this case.

then use the getbrush, gettexture and gettexturename functions to determine which texture files are used by which surface (see SaveB3D example in the code archives on how to use them) and bare in mind: getbrush and gettexture will create a copy of the brush or texture, so it must be frred after finding the texture path.
The texture path returned by gettexturename incudes the full path, so you might use t$=replace(path$,currentdir$(),"") to remove everything but the texture filename.

then you can run something like

if t$(i)="water.bmp" then
sndfile$(i)="water.wav"
snd(i)=loadsound(sndfile$(i))
endif

Tell me if there are still questions about this issue.


Mathieu A(Posted 2004) [#20]
Thank you JFK! it works very well.

I do all that you told me. But I store the surface handle, and texture name in a Type. like that

type Surface
field surface
field texture
field Material
end type

I've got other questions about that. Is it better to loadsound in the main loop, or initialise sound and playsound in the loop?

And I want to know another thing about mesh and optimisation. I've got my level compounded of 2 entities indoor and outside(same mesh). And when I'm outside i do not want to render the inside, so I need to Hide the indoor entity. I want to, does it better to use a loadanimmesh and access to the hierachy of the mesh or is it better to seperate my level in two static mesh(loadmesh) and then Hide the indoor mesh?

I'd prefer the first method if it's possible and not slower than the separate static mesh method, because I do a lightmap of all my level and it's easier to do with only one mesh.


jfk EO-11110(Posted 2004) [#21]
Don't use loadsound in the mainloop. Load them in the level loading process. then store their handle and simply use playsound handle in the mainloop.

Your 2nd question is not so easy to answer. Maybe you should use 2 Meshes with LoadMesh, and use the SAME lightmap file for both. Blitz will then load the lightmap only one time to optimize ram usage.

The problem with LoadAnimMesh is: all your Surfaces will then be Children again :/