A lot of problems in my music player function

Started by Georgeqgreg, Sun 05/02/2012 01:24:48

Previous topic - Next topic

Georgeqgreg

Hello! It's been a while since I was last here!

Anyway, in recent endeavours, I've been working on some other games. A game I'm currently working on has a few advanced things I'm using, and unfortunately, I seem to have broken it.

Anyway, I should describe the... err... function of my function. First, the game plays a song at the beginning. Then, when the song is done, it plays 1 of 5 songs, randomly. When this is done, it plays a different one. Here is my script code:

Code: ags
function musicplayer() {
while (aIntro.Play) {
  Wait(1);
}
int ran=Random(4);
if (ran=0) aCartown1.Play(eAudioPriorityNormal, eOnce);
if (ran=1) aCartown2.Play(eAudioPriorityNormal, eOnce);
if (ran=2) aCartown3.Play(eAudioPriorityNormal, eOnce);
if (ran=3) aCartown4.Play(eAudioPriorityNormal, eOnce);
if (ran=4) aCartown5.Play(eAudioPriorityNormal, eOnce);
while(aCartown1.Play) {
  Wait(1);
}
while(aCartown2.Play) {
  Wait(1);
}
while(aCartown3.Play) {
  Wait(1);
}
while(aCartown4.Play) {
  Wait(1);
}
while(aCartown5.Play) {
  Wait(1);
}
}


It's uhh... a bit messy! *grin*

Anyway, first error I get is on the first line. It's "GlobalScript.asc(385): Error (line 385): expected '('"

Now, I already have a (! What gives?

monkey0506

#1
You're trying to use the function AudioChannel.Play as a boolean property. That's why it's not working. And even if you added the parenthesis for Play(), then you'd still have problems as AGS evaluates non-null pointers as non-false...you'd constantly be restarting the audio clip (possibly on multiple audio channels)...

Seeing as you're calling Wait, the game would just hang indefinitely, never even triggering the 150000 loop check, because Wait allows the engine to update the screen and such.

Your function should look something more like this:

Code: ags
function musicplayer() {
  AudioChannel *channel = aIntro.Play(); // capture the AudioChannel* the clip is playing on
  while ((channel != null) && (channel.IsPlaying)) { // just for safety, make sure the pointer is non-null, then check if the channel is playing
    Wait(1);
  }
  int ran = Random(4);
  if (ran == 0) channel = aCartown1.Play(eAudioPriorityNormal, eOnce); // remember = is for assignment, == is for checking equality!, also keep track of the channel the clip is playing on
  else if (ran == 1) channel = aCartown2.Play(eAudioPriorityNormal, eOnce); // added else, as ran cannot have two different values
  else if (ran == 2) channel = aCartown3.Play(eAudioPriorityNormal, eOnce);
  else if (ran == 3) channel = aCartown4.Play(eAudioPriorityNormal, eOnce);
  else if (ran == 4) channel = aCartown5.Play(eAudioPriorityNormal, eOnce);
  while ((channel != null) && (channel.IsPlaying)) {
    Wait(1);
  }
}


I should also point out that:

QuoteFirst, the game plays a song at the beginning. Then, when the song is done, it plays 1 of 5 songs, randomly. When this is done, it plays a different one.

The way the function is currently written (both in the revised version here and yours above), it plays the intro clip every time the function is called. If that's not expected behaviour, you could easily make it play the intro only once by using Game.DoOnceOnly.

By the way, you may also want to check out the Playlist module. It could save you a lot of trouble. ;)

Georgeqgreg

Thanks for everything! Unfortunately, not only did the revised code, as you said it would, play the first song repeatedly, but it also made it impossibly to play the game! The wait command disabled the interface! (It was meant to wait for the song to finish!)

Thanks for the module suggestion too. I'm going to try that instead, it may be what I want. Thanks for everything! Sorry to waste your time! (?)

monkey0506

#3
Yes, well, Wait is a blocking function. The playlist module will allow you to queue audio clips in a non-blocking fashion.

You would want to do something like this:

Code: ags
// game_start
  Playlist.AddClip(aIntro);
  Playlist.AddClip(aCartown1);
  Playlist.AddClip(aCartown2);
  Playlist.AddClip(aCartown3);
  Playlist.AddClip(aCartown4);
  Playlist.AddClip(aCartown5);
  Playlist.Repeat = eRepeat;
  Playlist.Shuffle = ePlaylistShuffleNone; // just until we play the intro

// later...

function musicplayer()
{
  if (Playlist.IsPlaying) // playlist is already playing...
  {
    if ((Playlist.PlayingClip != aIntro) && (Game.DoOnceOnly("music intro")) Playlist.RemoveClip(aIntro); // *see comment below
    return; // if the playlist is already playing, ignore the following commands
  }
  Playlist.Play(); // start the playlist playing
  Playlist.Shuffle = ePlaylistShuffleRandom; // update the shuffle status, use ePlaylistShuffleAll if you prefer
}

// presumably, you are calling musicplayer from rep_ex...


You haven't wasted anyone's time though. This question is better suited to the beginner's forum but it's understandable that you wouldn't have asked for help if you had recognized why the code was wrong (and therefore understandable that you posted here). I would recommend that you go through the scripting tutorial in the manual just to make sure that you're understanding some of the more basic concepts (like assignment vs comparison). Other than that, it will come with time. ;)

*NOTE: I've actually discovered a bug in Playlist v1.0's RemoveClip function. It doesn't check that the clip is in the playlist, or even exists (ie., there's no null check). Because of that I've used Game.DoOnceOnly to ensure that the function is only called where appropriate.

Georgeqgreg

Right. Already worked out my own solution, but yours is more elegant! I wasn't aware of a RemoveClip function! :/

Oh yeah... you should probably be aware that your little module calls some files that don't exist. This part of code generated a compile error.

Code: ags
if (clip == aFlyOnTheWings) return "Fly";
if (clip == aSimpleAndClean) return "Simple";
if (clip == aMrBrightside) return "Brightside";



Thankfully, commenting them out seems to have had no ill effects. Wanted to post it in the module's thread, but the forum warned me that it may not have been a great idea. (Unintentional bump?) Thought you should know, though...

monkey0506

Egads! Yes, I have a bad habit of putting debugging code that *should* be in the global script into my module scripts. I edited my post above. And to be clear, v1.0 never had a full function list provided.

For these reasons (including the bug I discovered in the Playlist.RemoveClip function), I will try and get Playlist v1.1 uploaded in the next few days.

Georgeqgreg

Good, it's a bit of an embuggerence how Removeclip stops the track playing... (With the way I was gonna use it...)

Great program! Keep it up and this could be one of the most important AGS modules! (Unless equivalent function is ever provided within AGS itself. *grin*)

monkey0506

Thanks for that feedback, I can actually update the RemoveClip function to take an optional parameter as to whether or not the clip should be stopped playing. I'm reviewing the code and there's not technically a reason why it has to be stopped when removed, I can keep the pointers. I do need to just document that Playlist.PlayingClip may not always be contained within the playlist at all times. ;)

This is one of the reasons why having someone else actually using your code can be helpful, even for someone with experience such as myself. Like I said, I'll try and get it uploaded before too long. Please PM me if I don't! :D

Georgeqgreg

I'd love you if you'd do that! Anyway, I probably won't be around to ensure a timely release. It's getting late here and I'll probably go to bed soon. Thanks, though!

SMF spam blocked by CleanTalk