Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - Gal Shemesh

#21
Quote from: Crimson Wizard on Sun 03/09/2023 18:21:38By the way, I think you also need to test if PlayingClip is not null in the above code, in case the channel was assigned, but it does not play anything at the moment.
Correct, thanks! I just came to update my previous post to mention this in case someone else wishes to do the same, as my previous code will cause the game to crash if there's no sound playing, due to the null pointer. So one can just check for 'Game.IsAudioPlaying' instead of checking if the Audiochannel is not null, as you previously suggested me to check instead of checking the Audiochannel type.

Code: ags
if (Game.IsAudioPlaying(eAudioTypeMusic))
{
  lblMus1Vol.Text = String.Format("Music clip: %s[Vol: %d", 
  globalChannelMusic1.PlayingClip.ScriptName, globalChannelMusic1.Volume);
}
else
{
 lblMus1Vol.Text = String.Format("Music clip:[Vol: 0");
}

This works great and does not crash when there's no sound playing, but for my scenario with the different 'audio channels logic' using global variables, I should fix it according to what you just added. Many thanks! :)
#22
QuoteIf you want to access particular clip's property, you need to also add this property to command, like "channel.PlayingClip.ScriptName".
Awesome!!!  8-)  8-)  8-)  Thank you so much! This works flawlessly.

EDIT:
See @Crimson Wizard's clarification below; an additional check is required to prevent null pointer crash.
#23
QuoteYes, you can access a played clip properties through channel.PlayingClip.
Mm... I tried pulling the name as a string this way but it doesn't work... I guess my code is incorrect.
Code: ags
if (globalChannelMusic1 != null)
{
  lblMus1Vol.Text = String.Format("Music (Ch1): %s[Vol: %d", globalChannelMusic1.PlayingClip, 
  globalChannelMusic1.Volume);
}
else
 {
   lblMus1Vol.Text = String.Format("Music (Ch1): [Vol: 0");
 }
#24
Awesome, @Crimson Wizard! :) I'm always using the latest stable release, currently Build 3.6.0.50, v3.6.0, July 2023. But I do look forward for the official release of 3.6.1 with all the new added features - especially the fully supported right-to-left Hebrew fix for GUI buttons.

I have downloaded the 3.6.1 version from your link for a test run and monitored this function in the new Log Panel when the game starts - this is really awesome! I see that it prints all the imported sounds in an array and that each can be retrieved by its number from the log.

Can the retrieval be dynamic? I mean, if a global variable is set as an Audiochannel* and I dynamically change it to other sounds, can the name of the actual sound that plays be retrived? I have this label in my debbuger GUI and I'm currently running this in the 'repeatedly_execute_always()' function in the Global Script for monitoring the sound volume, but I wish to add the sound name as well:

Code: ags
if (globalChannelMusic1 != null)
{
  lblMus1Vol.Text = String.Format("Music (Ch1) Vol: %d", globalChannelMusic1.Volume);
}
else
{
  lblMus1Vol.Text = String.Format("Music (Ch1) Vol: 0");
}

Thanks
#25
Thanks @Cassiebsg - but doesn't AGS calculate and position according to the 'bottom-center' of the sprites boundaris (its feet)? I mean, if it calculates from the center as you say, wouldn't the center point change if the overall boundaries size of the character changes? See picture below.



I'm aware of problems like this from other game engines, where if you change the boundaries of a sprite from the Left or Top then it affects its 'hotspot' - causing its center point to change and the character to jump around when its now 'non-gap' sprite that you changed plays in a sequence with other animations that still have a gap in them. While if you change its boundaries from the Right or Bottom then the hotspot remains in place; a trick I used back when I was working on other game engines that gives you control over the hotspot position in a given sprite/frame, was to flip the image to the other side than the side I wish to change the boundaries from, to make the size change, and then to re-flip the sprite back, which kept its hotspot in place. But I didn't see a way to manually modify sprites/frames hotspot in AGS...

Anyway, I've successfully finished working on this game I was working on by now, along with successfully fixing all its scripting issues coming from the old AGS 2.72 - it was a 'making captions' project for a game that didn't had captions in the first place, only speech. But this note of yours is something to take into account if I encounter with such thing while working on other AGS projects that aren't mine in the future.
#26
Thank you so much @Crimson Wizard for the detailed information! I will take your example and spend some good time studying it, as there are many aspects in it that I wasn't aware about or ever used yet.
#27
I know the last reply on this thread is from a few years ago, but just wondered if we can easily grab the name of audio clips for debugging by now?

Like @Laura Hunt, I also built a custom 'audio channels logic' where I have global variables for either Music, Ambiance and SFX, where each is set as Audiochannel*, and I play music for example like so:

Code: ags
globalChannelMusic1 = aMain_Menu.PlayOnChannel(1, eAudioPriorityNormal, eRepeat);

I'm already debugging the 'Volume' of my 'globalChannel' variables, but I'm also interesting in seeing the actual name of the audioclips in a label on my debugging GUI.

Thanks
#28
Quote from: Crimson Wizard on Tue 22/08/2023 14:43:10In case of SayBackground, it returns an Overlay pointer, which you may store in a variable and test for Overlay.Valid to know when it's removed, so that you could continue with the next SayBackground.
That's an interesting one - can you kindly explain how do I save the Overlay pointer of SayBackground and check for it using the Overlay.Valid for triggering the next speech line?

I saw in the manual the 'Overlay.CreateTextual' example, though it doesn't speak on the specific SayBackground function. I made a custom SayBackground function called 'SayBackgroundNew' and it looks like this:

Code: ags
void SayBackgroundNew(this Character*, int cue, String text)
{
  String cueString = String.Format("&%d", cue);
  {
    if (Speech.VoiceMode == eSpeechVoiceAndText && IsSpeechVoxAvailable())
    {
      Game.PlayVoiceClip(this, cue);
      this.SayBackground(text);
    }
    else if (Speech.VoiceMode == eSpeechVoiceOnly && IsSpeechVoxAvailable())
    {
      this.Say(cueString);
    }      
    else if (Speech.VoiceMode == eSpeechTextOnly)
    {
      this.SayBackground(text);
    }
  }
}

And I call for it in the 'room_RepExec()' like this:

Code: ags
player.SayBackgroundNew(1, "first speech cue text");
player.SayBackgroundNew(2, "second speech cue text");

Thanks
#29
Completed Game Announcements / Re: Going Home
Fri 25/08/2023 14:20:59
Thanks a lot, @heltenjon! Very pleased to hear that you liked it and that it works flawlessly - I really tried my best to make it covered from every direction to provide the best playing experience. Glad to receive such feedback and that all my hard work is appreciated.

Will very appreciate the votes on the game's page from whomever played it.

Thanks everyone. :)
#30
Thanks for the explanation. I actually did set all my audio types in the editor to 1, to make sure that new sounds that I play on a given 'globalChannel' variable will play on the same channel as the previous. But, does it means that there will be 1 channel preserved for each type, meaning a total of 3 (Ambient, Music, SFX)? Or that there will be 1 channel in general for everything?

EDIT:
Ended up making 3 silent audio files of 1 second each (empty audio file makes AGS crash). I then set them as follows when the game starts:
Code: ags
function game_start()
{
 globalChannelAmbiance = aSilent_Ambiance.Play(eAudioPriorityNormal, eOnce);
 globalChannelMusic = aSilent_Music.Play(eAudioPriorityNormal, eOnce);
 globalChannelSFX = aSilent_SFX.Play(eAudioPriorityNormal, eOnce);
}
Now each 'globalChannel' variable is preserved for sound assets of its type.
#31
QuoteDo you assign globalChannelSFX  to something in the main menu room script perhaps?
Yes, just edited my previous post. There was a click of a button that is set using the globalChannelSFX. Thanks!!

I've just set a sound asset to play on all the globalChannel variables that I made when the game starts, which changes them all from being 'null'. Now at least the game doesn't crash on me. So I'll probably make a short silent sound file for this purpose. Thing is, when a SFX is playing the labels of both the SFX and Ambience go to 100% from some reason, while only the SFX label should do so.

My current code state is after following your suggestion above, set to check for my 'global channel' variables instead of the 'Game.IsAudioPlaying'. I'm not sure why, but when I change it back to check for the 'Game.IsAudioPlaying' of each type, each label now works for what it meant to check. Though, I'm trying to figure out why the labels of both Ambience and SFX are affected when only a SFX is playing when the checks are set to check the 'global channel' variables, as you recommend to do it this way.

#32
Yes, I thought so too - but the SFX label goes from 0 to 100% when a SFX that I set in a given frame is playing... So globalChannelSFX does change from null - that what I expected to happen as I've set my SFX assets in advanced as 'SFX' type, and it appears like this is what makes it work; I've just tried changing the SFX to be of another type to see if there's a difference, and yes - the other type now changes from being null to represent the values.

The thing that drives me crazy is that the debugging labels work only if I test my game from the the 'main menu' room. If I set my player character to start in a higher room number, which does have sound effects going on in it, the SFX label don't update. By checking the code of the main menu room I don't see anything special that makes it work only when launching the game from that particular room. I'm really clueless...

EDIT:
Ok. Figured why it worked only when launching from the main menu - the main menu 'new game' button has a click sound of the SFX type that I set to play using 'globalChannelSFX = aClick.Play();' -- that what made the globalChannelSFX to change from being null, and so the next rooms sound effects also affected the SFX label to show their volume when they're play.
#33
Thanks for the prompt reply, CW. Here's what I did so far:

For playing music, I wrote this under 'room_Load()':

Code: ags
globalChannelMusic = aMain_Menu.Play(eAudioPriorityNormal, eRepeat);

For playing ambience sound, I wrote this under 'room_Load()':

Code: ags
globalChannelAmbiance = aWind.Play(eAudioPriorityNormal, eOnce);

For playing sound effects - which up to this point in the game I'm buliding is during the introduction cut-scenes - I'm using this custom function in my Global Script header for assigning sounds that I've imported into AGS to specific frames:

Code: ags
void playAudioClipOnFrame(this Object*, int loop, int frame, AudioClip* sound)
{
  ViewFrame* vf = Game.GetViewFrame(this.View, loop, frame);
  vf.LinkedAudio = sound;
}

And under 'room_RepExec()' I'm setting the sounds to the frames, for example like so:
Code: ags
oEgyptRun1.playAudioClipOnFrame(0, 126, aGUNSHOT1); // first gun shot
oEgyptRun1.playAudioClipOnFrame(0, 149, aGUNSHOT2); // second gun shot
#34
Here's the thing:

When debugging my game, I wish to keep track on the volume when my music, ambience and sound effects are playing. For this, I have to also keep track on which AudioChannel* variable type I set for playing them. So I've created 3 global variables of the AudioChannel* type for this purpose, for setting to play my sounds, as follows:

- globalChannelMusic
- globalChannelAmbiance
- globalChannelSFX

In my debugging GUI, I've created 3 labels to represent their Volume, as follows:

- lblMusVol
- lblAmbVol
- lblSFXVol

In my 'repeatedly_execute_always()' function in my Global Script, I've wrote this code:

Code: ags
if (Game.IsAudioPlaying(eAudioTypeMusic))
  {
    lblMusVol.Text = String.Format("Music Volume: %d", globalChannelMusic.Volume);
  }
  else
  {
    lblMusVol.Text = String.Format("Music Volume: 0");
  }
  if (Game.IsAudioPlaying(eAudioTypeAmbientSound))
  {
    lblAmbVol.Text = String.Format("Ambiance Volume: %d", globalChannelAmbiance.Volume);
  }
  else
  {
    lblAmbVol.Text = String.Format("Ambiance Volume: 0");
  }
  if (Game.IsAudioPlaying(eAudioTypeSFX))
  {
    lblSFXVol.Text = String.Format("SFX Volume: %d", globalChannelSFX.Volume);
  }
  else
  {
    lblSFXVol.Text = String.Format("SFX Volume: 0");
  }

Now, I'm not sure what happened, but in the first room that a sound effect is playing on a specific frame, the label changes to show its 100% volume without any problem.

In another room, I've did the very same thing (copied and pasted the code) and set it to play a different SFX. However, immediately when the sound effect is playing, it gives me the 'Error running function 'repeatedly_execute_always': Error (line 38): Null pointer referenced'.

I really don't know what happened and how come that it works in previous rooms and in the new room that I'm working on now it doesn't. I've checked the imported sound effect asset and it is set like the others as a SFX type. What am I doing wrong?

Thanks

EDIT:
I've found that if I run the game from the very beginning, the game does not crash. But if I set my player character to start in the current room I'm working on to test it from there, it crashes when the SFX is playing...
#35
Thanks, @Khris! Much appreciated. I guess it makes things more complicated for me... Well, maybe it will be supported in AGS in the future. :)

EDIT:
Meanwhile, I ended up adding the specific speech files used in the cut-scenes directly into AGS, and now they can be assigned to 'view' frames same as I can do with SFX under the 'room_Load()' function - not the best approach I was after, but it sort of works. This is the custom function I'm using:

Code: ags
void playAudioClipOnFrame(this Object*, int loop, int frame, AudioClip* sound)
{
  ViewFrame* vf = Game.GetViewFrame(this.View, loop, frame);
  vf.LinkedAudio = sound;
}
Though, I eventuaully found that assigning speech files to be played in specific frames with the above method for 'cut-scenes' in particular became into a tedious process, as there are quite some dialogues in the 'cut-scenes' and it requires to actually import all the relevent speech audio files into the editor - which isn't ideal. So instead, I found that if I use a simple 'if' statement to check for a specific 'cut-scene' frame, I can actually just use the regular '.SayAt' function under 'room_RepExec()', which pulls the speech directly from the external 'Speech' folder.

Here's an example of a cut-scene, which is basically a background and an object playing a cropped animation view of the moving area of the scene:



Here's the custom '.sayNew' function code of the above screenshot:

Code: ags
function room_RepExec()
{
  if (oZepConversation.Frame == 65)
  {
    cRob.sayNew(6, "I'm lucky I made it out of Egypt.");
  }
}

And this is the actual code of the custom speech function:

Code: ags
void sayNew(this Character*, int cue, String text)
{
  String cueString = String.Format("&%d", cue);
  {
    if (Speech.VoiceMode == eSpeechVoiceAndText && IsSpeechVoxAvailable())
    {
      AudioChannel* ch = Game.PlayVoiceClip(this, cue);
      this.SayAt(Game.Camera.Width /2, Game.Camera.Height + 15, -1, text);
      if (ch != null)
      {
        ch.Stop();
      }
    }
    else if (Speech.VoiceMode == eSpeechVoiceOnly && IsSpeechVoxAvailable())
    {
      this.Say(cueString);
    }      
    else if (Speech.VoiceMode == eSpeechTextOnly)
    {
      this.SayAt(Game.Camera.Width /2, Game.Camera.Height + 15, -1, text);
    }
  }
}

But there are 2 issues that I face now, which I'm trying to solve by my own for quite some time using the manual and forum search, however so far I haven't found a solution - perhaps you or someone else can assist on this one:

1. When there's a speech line that is triggered to be said before that a previous line's text has been removed from the screen, the new line 'slips through the cracks' and not said at all, since the '.Say' function doesn't return immediately - so basically the frame check that suppose to play the next speech line is passed before the previous speech text has been removed from the screen, missing the only chance it has to play it. For example:

Code: ags
if (oZepConversation.Frame == 65)
{
  cRob.sayNew(6, "I'm lucky I made it out of Egypt.");
}
if (oZepConversation.Frame == 83)
{
  cMei.sayNew(4, "What did they want?"); // <- this line 'slips through the cracks'
}

So I'm trying to figuring out how to make my custom '.sayNew' function to actually 'interrupt' any previous speech text and to remove it from the screen immediately when it is called (like when the players can manually skip text lines, only upon call), so the next '.sayNew' could be triggered without interference. Currently it doesn't return to the code until the speech text is automatically removed.

2. Players are able to skip speech lines, which I want during the game, but not in 'video like' cut-scenes animation like I have above - as skipping the text is irrelevant since the players will then see a 'muted' cut-scene animation until the next frame that triggers the next speech line is reached. So I'm trying to prevent skipping the text lines specifically during cut-scenes.

I've found that playing the speech audio separately and using the '.SayBackground' function to display the text is almost best to bypass both issues above, which both prevents skipping and return to the code immediately. So any triggers for next speech lines are successfully checked on time:

Code: ags
if (oZepConversation.Frame == 65)
{
  Game.PlayVoiceClip(cRob, 6);
  cRob.SayBackground("I'm lucky I made it out of Egypt.");
}
if (oZepConversation.Frame == 83)
{
  Game.PlayVoiceClip(cMei, 4);
  cMei.SayBackground("What did they want?");
}

However, it has its flaws:

1. Text cannot be positioned anywhere I like, same as I can do with '.SayAt', which also allows me to set '-1' for the text width for having a nice one-line of text. for this; I found that I can bypass this by positioning the characters at the bottom center of the screen where I want the text to be shown and to make them transparent. However, there is no text 'width' option to set in this function, and so long text lines automatically break into new lines, which in most cases put a 'single' or 'two words' on a second line because it ran out of space, which looks odd.

2. If 2 characters' speech lines are triggered close to each other in time, an overlapping of the speech text may occur; I found that I can bypass this by passing a 'Character.SayBackground("");' for the previous character that spoke, just before the speech line of the next character, which wipes the previous character's text and prevents this overlap.

3. It requires 2 separate lines for each cue; for playing the speech and for showing its text - this can be easily combined in a custom function, but I'll first need to solve the 2 issues above of positioning the '.SayBackground' text in specific X and Y coordinates, and to have its width as '-1' to prevent oddly line breaks.

Would appreciate some help. :) Thanks
#36
That's awesome, @Khris. Thanks!
Though, unfortunately - my game uses bare WFN pixel fonts. So I can't upload my files there...
#37
Is there a way to also use characters 'speech' files to play on a specific frame in an animation?
Currently the conversation I have is a close-up photographed footage of a conversation between two characters (not the actual characters during play mode but like a cut-scene video). And I'm willing to use my custom 'Say' function during the conversation animation, which shows their text at the bottom of the screen.

I was trying to do it this way, but of course it doesn't work at I used the 'Game.PlayVoiceClip' which plays the voice clip - not set it. Is there a way to set an assignment of a voice clip to a specific frame?

Code: ags
oConversation.playAudioClipOnFrame(0, 2, Game.PlayVoiceClip(cMei, 1);

Thanks
#38
Thanks CW! Just edited the latest message of mine while you posted yours, after seeing that @Snarky already reported a feature request there. :)
#39
Hi everyone, hope you're all doing well.

I've posted this in the 'Beginners' Technical Questions' forum and was suggested to report a problem here. Would appreciate if this could be fixed:

The current Project tree has a behavior of auto-collapse of folders in certain sections, such as in VIEWS and AUDIO.

If for example you create folders in these sections and then drag and drop assets from one folder to another in the same section, all the expanded folders in that section get collapse, and only the one that you dragged the asset into opens / remains open. This makes organizing of assets very difficult, especiallly if you have many sub-folders.

As far as I've checked, this happens in the VIEWS and AUDIOsections, and I just tested if it happens in the CHARACTERS section and it does - so I guess that it behaves that way in any place in the Project tree that can have folders in it.

Thanks
#40
Thanks CW for the prompt reply and info. Really appreicate it.

I'd love to report this as a problem and much appreciate if this could be fixed. I also thing that it would be great to have an option to update the sound files from source, like we can do in the Sprites editor. But just saw that @Snarky already posted a feature request about this.

I've reported this now in the 'Editor Development' forum.
SMF spam blocked by CleanTalk