[SOLVED] Some help with eyes following player, Please.

Started by RetroJay, Mon 16/01/2012 22:22:37

Previous topic - Next topic

RetroJay

Hi Peeps.

Ok. I have a room that has a pair of eyes, within a wall, set right in the centre of the screen.
The eyes are made up of three objects. 1-eyes left, 2-eyes right and 3- eyes centre. These are on top of each other so they can be switched on or off.

Now on the walkable area, going across the screen and under the eyes, I have set three regions. 1- left side of room, 2- right side of room and 3- just under eyes.
I you are on the left side of screen, on region 1, the eyes look left. If you are on the right side of screen, region 2, the eyes look right and if you are under the eyes, region 3,
the eyes look down at you and a sound is played, just once.

I have written the script for each of the eyes, objects,  to turn off or on depending on what region the player is standing. I used the 'Player walks onto region' for all three.

This works just how I want it to... However I have come across a problem.

On the right side of the screen is a 'switch', this is a hotspot and has a walk to set which is set to 'eblock' because the player walks up to switch and says things about it.
If you are on the right side of screen and click on the switch, no problem, the eyes are looking at you.
But if you are on the left side of the screen, eyes are looking at you, until you click the switch.
The player then walks across the screen, under the eyes, and to the switch says what he knows about it and then, only after he has finished, does the eyes look at him and plays
the sound.

I know what the problem is. It's because of the bloody blocking but I just can't fix it.
I have tried using rep-execute-always but still no joy.

I am sorry for this long message but I wanted to explain my prob as thoroughly as possible. :-[

What am I doing wrong?
Is there an easier way to achieve what I am trying to do?

Many, Many thanks.
Jay.
 

Khris

#1
Hi Jay,

rep_ex_always is indeed what you need.
Furthermore you don't need three objects, you can simply assign a different sprite to the same object.

Code: ags
bool play_eyes_sound = true;

function repeatedly_execute_always() {

  if (player.Room != NUMBER_OF_ROOM_WITH_EYES) return;  // exit function if not in room with eyes

  Region*rr = Region.GetAtRoomXY(player.x, player.y);
  if (!rr.ID) return;  // player not on region

  if (rr.ID == 1) {
    object[EYES_OBJECT_ID].Graphic = EYES_LOOK_LEFT_SLOT;
    play_eyes_sound = true;
  }
  if (rr.ID == 2) {
    object[EYES_OBJECT_ID].Graphic = EYES_LOOK_RIGHT_SLOT;
    play_eyes_sound = true;
  }
  if (rr.ID == 3) {
    object[EYES_OBJECT_ID].Graphic = EYES_LOOK_STRAIGHT_SLOT;
    if (play_eyes_sound) {
      EYES_SOUND.Play();
      play_eyes_sound = false;
    }
  }
}


Now replace all the all-caps stuff with the appropriate numbers/names.

Edit: code corrected

RetroJay

Hi Khris.

WOW! :o
That looks fantastic.

This should be just what I need.
I will have to try it out tomorrow, though.
I will let you know how it goes.

I have to say. There are quite a few things here that I haven't used before.
I would like to understand, if it works, how it works.

Thank you for your time, Khris.
Jay.

RetroJay

Hi Khris.

With your script the eyes now follow the player perfectly.

However. I can't get my sound for when the eyes look down.
I had my sound for this originaly set like so.

Code: ags

PlaySoundEX (6,4);  // sound 6 on channel 4
SetChannelVolume (4,100);  // Channel 4. Volume 100. as the sound file is quiet.


I have the script you gave me placed in 'Global Script' like so.

Code: ags

bool play_owl_hoot = true;


function repeatedly_execute_always() {

  if (player.Room != 16) return;  // exit function if not in room with eyes

  Region*rr = Region.GetAtRoomXY(player.x, player.y);
  if (!rr.ID) return;  // player not on region

  if (rr.ID == 1) {
    object[1].Graphic = 96;
    play_owl_hoot = true;
   
  }
  if (rr.ID == 2) {
    object[1].Graphic = 95;
                             // This is where I need a sound to play.
                             // My sound file for this is called 'sound6'
                             // .Play() won't compile.
    play_owl_hoot = false;

  }
  if (rr.ID == 3) {
    object[1].Graphic = 97; 
    play_owl_hoot = true;
  }
} 


Everything works a treat, except for the sound FX.
If I put my couple of lines in the script, for when the eyes look down, the sound works but plays constantly all the time player is on the region.

Please. Can you see anything I have missed or done wrong?
I probably should have mentioned that this is the last thing I need to do with AGS 2.72. I will then go over to 3. I promise. ;)

Many thanks.
Jay.

Miglioshin

#4
Hi Retrojay,
I think you can simply add, where you need your sound to be played, the line:

if(Game.DoOnceOnly("play_eyes_sound"))
  {
    PlaySoundEX (6,4);
    SetChannelVolume (4,100);
  }

This will tell AGS to play that sound effect just ONCE (the first time it come across the condition); because of your instructions are in the repeatedly_execute_always function, AGS will play that sound each cicle (40 per second) because the condition will be continuosly true while the player walk through that specific region.

And if this works properly (it should do) the bool become useless.

Or you can just change this:

  if (rr.ID == 2) etc...

in this:

  if (rr.ID == 2)
  {
    object[1].Graphic = 95;
        if(play_owl_hoot == true)
          { PlaySoundEX (6,4);
             SetChannelVolume (4,100);
             play_owl_hoot = false;
           }
   }



RetroJay

#5
Hi Miglioshin.

Thank you... wonderfull... Fantastic. :D

That has solved my sound issue.

This is, now, what I have in 'Global Script'.

Code: ags

// Lines beneath are for Owl in Cemetary.

bool play_owl_hoot = true;


function repeatedly_execute_always() {

  if (player.Room != 16) return;  // exit function if not in room with eyes

  Region*rr = Region.GetAtRoomXY(player.x, player.y);
  if (!rr.ID) return;  // player not on region

  if (rr.ID == 1) {
    object[1].Graphic = 96;
    play_owl_hoot = true;
   
  }

  if (rr.ID == 2) {
    object[1].Graphic = 95;
        if (play_owl_hoot == true) {
          PlaySoundEx(6, 4);
          SetChannelVolume (4,100);
          play_owl_hoot = false;
      }
  }

  if (rr.ID == 3) {
    object[1].Graphic = 97; 
    play_owl_hoot = true;
  }
} 

// Owl in Cemetary : End.


I don't know if this is the neatest. But... It works. :)

Thank you, Khris and Miglioshin for your help.

Jay.

Miglioshin

#6
Hmmm...
Actually the function, as it is now, changes the object graphic at each cicle, even when the correct sprite is displayed.

If you want AGS to exit the function when it has done what you need (played sound and/or set the bool to false or true) you have to add another if contition to have it checked 'every first time' the player walks on the specified region, like this:

 if (rr.ID == 1 && object.[1].Graphic != 96) \\The sprite isn't #96 otherwise return
{
   object[1].Graphic = 96;
   play_owl_hoot = true;
 
 }

 if (rr.ID == 2 && object.[1].Graphic !=95)  \\Ditto
 {
   object[1].Graphic = 95;
   PlaySoundEx(6, 4);
   SetChannelVolume (4,100);
   play_owl_hoot = false;
 }

 if (rr.ID == 3 && object.[1].Graphic !=97)  \\Ditto
 {
   object[1].Graphic = 97;
   play_owl_hoot = true;
 }

With theese changes, the 'if (play_owl_hoot == true)' etc, becomes redundant, since we have already checked if the sprite has changed we don't need to check also the satate of the bool, we change it when we change the displayed sprite, so we can remove that if condition.

EDIT: I guess, in fact, that you can completely remove the bool, because now you are using the sprite number as discriminating factor...

  if (rr.ID == 1 && object.[1].Graphic != 96) \\The sprite isn't #96 otherwise return
{
    object[1].Graphic = 96;
  }

  if (rr.ID == 2 && object.[1].Graphic !=95)  \\Ditto
  {
    object[1].Graphic = 95;
    PlaySoundEx(6, 4);
    SetChannelVolume (4,100);
  }

  if (rr.ID == 3 && object.[1].Graphic !=97)  \\Ditto
  {
    object[1].Graphic = 97;
  }

Maybe this is a little neater, at least imho, but I'm not the best here around  ;)

Khris

Right, I put in the bool, set it everywhere and then forgot to check its value... :=
I have corrected the code.

Game.DoOnceOnly is of no use here since it'll return true only once during the entire game.

And yes, it's not the best form to unnecessarily set the Graphic each game loop but it doesn't waste time or resources so I kept it simple.

Jay:
Regarding .Play():
That's the new audio system, introduced in 3.2.
I didn't remember that you're still using 2.72.
So yeah, high time to make that transition :)

RetroJay

Thanks guys.

This is all very interesting, and slightly confusing. ???

So... This is what I have now.

Code: ags

// Owl looks at EGO, left, right and centre.
  
  bool play_owl_hoot = true;

  function repeatedly_execute_always() {

  if (player.Room != 16) return;  // exit function if not in room with eyes.

  Region*rr = Region.GetAtRoomXY(player.x, player.y);
  if (!rr.ID) return;  // player not on region.

  if (rr.ID == 1) {  // Owl looks Left.
    object[1].Graphic = 96;
    play_owl_hoot = true;
  }

  if (rr.ID == 2) {  // Owl looks Right.
    object[1].Graphic = 97; 
    play_owl_hoot = true;
  }
  
  if (rr.ID == 3) {  // Owl looks Down.
    object[1].Graphic = 95;
    if (play_owl_hoot) {
      PlaySoundEx(6, 4);
      SetChannelVolume (4,100);
      play_owl_hoot = false;
    }
  }
} 
// Owl in Cemetary : End.


This, also, works like a charm. I am so pleased. :)

Khris. Am I right in assuming that your code is to be only placed in 'Global script'?
Could Miglioshin's code, though, be placed in the 'Room Script'?

I don't know. I am torn between the two ways of doing this.
Help... Which one is the best way for me?

I really appreciate the help both of you have given me.

Jay.

Khris

Quote from: RetroJay on Wed 18/01/2012 23:25:05Could Miglioshin's code, though, be placed in the 'Room Script'?
Unfortunately, no.
In principle it's much tidier to do stuff like this in the room script instead of the global one, yes.

However, since we have to use repeatedly_execute_always, we have to put the code into the global script.
Only the repeatedly_execute variety can be used in a room script (via the room's RepExec event), but as you know, this doesn't get called during blocking events.

The only global functions that can also be directly added to a room script are on_key_press and on_mouse_click.

Miglioshin's suggestions were only about the contents of repeatedly_execute_always.

RetroJay

#10
Khris.

Yes. I understand what you are saying. Thank you, again, for your help.
Are you sure you want me to go to 'AGS 3'. I may bug you some more.  ;)

Miglioshin.
Thank you for your help.
Without you my sound wouldn't have played... now it does. :)

Many, Many thanks to you both.

Jay.

Khris

Unless you were using the Interaction Editor for other things than just adding a RunScript action, the transition should be relatively smooth. In other words, the biggest change is that you have to script everything now.

The v3 editor's interface is a lot more streamlined and there are tons of bugfixes since 2.72.

There are special sections in the manual for people who switch to 3.X, and there are of course Densming's youtube tutorials, slightly outdated, not perfect, but close enough and surely a big help for people who just switched to 3.X.

RetroJay

#12
The change over shouldn't be to difficult, I hope.

I have been testing 3 and like the changes, so far.
Also I have viewed some of Densming's Tutorials already, just to get me up to speed.

My ETA on 'Lost Prince' has been screwed up cos of work and other issues.
I need to get it finished on 2.72 though cos of the 'lake module'.

I tried to port 'Lost Prince' to AGS 3 to finish it but all Hell broke loose.

Why I'm bothering, I don't know.
It's 'Part 1' and taken me too long to do.

If people like it then I may do 'Part 2'...  That will be written with AGS 3, Though.

EDIT:
I may P.M you at some time, if you don't mind, as I have a game idea that you may like to help with.
I just need to think about it some more before I do.

Jay.

Kweepa

Quote from: Khris on Wed 18/01/2012 23:46:18
Quote from: RetroJay on Wed 18/01/2012 23:25:05Could Miglioshin's code, though, be placed in the 'Room Script'?
Unfortunately, no.
...since we have to use repeatedly_execute_always, we have to put the code into the global script.
FYI, you can add a function repeatedly_execute_always() to a room script, and it will just work.
Still waiting for Purity of the Surf II

Khris

Indeed, I stand corrected, and of course it says so in the manual, too. :P
In fact, thinking about it, I'm positive I've already done that in the past.

However last time I wanted to re-check whether it's possible, I didn't even bother to try myself and relied on the last paragraph of the section:
QuoteThe on_key_press and on_mouse_click events can also be handled by individual room scripts. ...

So Jay,
you can in fact move over the code to room 16's script, and of course take out the check for player.Room != 16 at the beginning.

Also, PM'ing me with technical questions is fine but I'd rather you open a thread here (unless of course it's about one of my modules or something like that).

RetroJay

Hi all, again.

I want to thank everyone who has helped with my problem.

Khris, Miglioshin and Kweepa.

Khris, With code.
Miglioshin, With sound.
Kweepa, With placing of script.

My room works just how I want it to.
Thank you, all.

Much appreciated.
Jay.

SMF spam blocked by CleanTalk