Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Sample unit to implement randomization of sounds in Castle Game Engine. See https://github.com/castle-engine/castle-engine/wiki/Upgrading-to-Castle-Game-Engine-7.0
{ Sample unit to implement randomization of sounds,
after the feature was removed from CGE sounds XML file.
See https://github.com/castle-engine/castle-engine/wiki/Upgrading-to-Castle-Game-Engine-7.0
for documentation.
Copyright 2021 Michalis Kamburelis.
License: modified BSD (3-clause), so basically reuse it freely (see
https://github.com/castle-engine/castle-engine/blob/master/doc/licenses/COPYING.BSD-3-clause.txt ).
Usage:
- replace SoundEngine.SoundFromName with TSoundChoice.Init
- replace TSoundType with TSoundChoice
- modify TSoundType.Init to implement your randomization
}
unit GameSound;
{$modeswitch advancedrecords}
interface
uses CastleSoundEngine;
type
{ Use this instead of TCastleSound and TSoundType.
The TSoundChoice supports randomization. }
TSoundChoice = record
Choices: array of TCastleSound;
class function Empty: TSoundChoice; static;
{ Use this instead of SoundEngine.SoundFromName.
The meaning of SoundName and Required params is the same.
When SoundEngine.SoundFromName would return @nil, this sets Choices to empty,
and then Choose will return nil. }
class function Init(const SoundName: String; const Required: boolean = true): TSoundChoice; static;
{ Return TCastleSound, doing randomization along the way. }
function Choose: TCastleSound;
{ Automatically converts TSoundChoice to TCastleSound (doing randomization along the way)
so that TSoundChoice can be used as a drop-in replacement of TCastleSound.
You can also do it explicitly by TSoundChoice.Choose. }
class operator := (const Value: TSoundChoice): TCastleSound;
end;
implementation
class function TSoundChoice.Empty: TSoundChoice; static;
begin
// SetLength(Result.Choices, 0); // actually this is default for dynamic arrays
Assert(Length(Result.Choices) = 0);
end;
class function TSoundChoice.Init(const SoundName: String; const Required: boolean): TSoundChoice; static;
procedure InitializeChoice(const Names: array of String);
var
I: Integer;
begin
SetLength(Result.Choices, High(Names) + 1);
{ This can place nil inside Result.Choices.
That is OK, let it (TSoundChoice.Choose will then return nil for them). }
for I := Low(Names) to High(Names) do
Result.Choices[I] := SoundEngine.SoundFromName(Names[I], Required);
end;
var
Sound: TCastleSound;
begin
case SoundName of
'fight/playerhurt': InitializeChoice([
'fight/playerhurt1',
'fight/playerhurt2'
]);
'hotel_room/roseanne_attack': InitializeChoice([
'hotel_room/pr_fight_sukkub_attack_1',
'hotel_room/pr_fight_sukkub_attack_2',
'hotel_room/pr_fight_sukkub_attack_3'
]);
else
begin
Sound := SoundEngine.SoundFromName(SoundName, Required);
if Sound <> nil then
begin
SetLength(Result.Choices, 1);
Result.Choices[0] := Sound;
end else
SetLength(Result.Choices, 0);
end;
end;
end;
function TSoundChoice.Choose: TCastleSound;
begin
if Length(Choices) > 0 then
Result := Choices[Random(Length(Choices))]
else
Result := nil;
end;
class operator TSoundChoice.:= (const Value: TSoundChoice): TSoundType;
begin
Result := Value.Choose;
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment