Buttons, idles and load screen

Started by Peegee, Mon 11/10/2021 14:57:25

Previous topic - Next topic

Peegee

Hello, newbie on this forum (by the way on all forums), I don't know is my technical questions will be well placed, thank you for helping me.
I started a game (for a few months) on AGS (great software!), Which will be called Gobliiins 5. I have some technical questions, there may be the solution in the manual but I do not understand everything, not perfect in English.

1- I am not very comfortable with GUI questions. On my "load a level" room, I would like to make a back button, but I don't see the button creation tool when I am on my room, what should I do?

2- For some actions, I prefer to hide a character and replace it with an object, but after a while the animated idle arrives, unexpectedly. How to deactivate idle momentarily?

3- When I load a level, if I start playing and load it again, I notice that it does not reset it. Is there a way for this or should I set the loading code to zero all items? I have very rich levels and dozens of variables.

Thanks in advance.

Crimson Wizard

#1
Hello.

Quote from: Peegee on Mon 11/10/2021 14:57:25
1- I am not very comfortable with GUI questions. On my "load a level" room, I would like to make a back button, but I don't see the button creation tool when I am on my room, what should I do?

GUI are completely separate from the rooms, they are created in their GUI editor. You could make a GUI, make it not visible by default, display it in the particular room using script command (e.g. gGui.Visible = true) and hide back in "room leave" event (gGui.Visible = false).
But there are other ways to make "buttons", for example you may also make one using a room object.
What method to choose depends on what is more convenient for you, and how do you make your "load level" screen.

Quote from: Peegee on Mon 11/10/2021 14:57:25
2- For some actions, I prefer to hide a character and replace it with an object, but after a while the animated idle arrives, unexpectedly. How to deactivate idle momentarily?

Answering your question directly, that would be Character.SetIdleView function, passing -1 as the "view" parameter would deactivate it, and later you would need to call it again with a proper view number to turn it back.
But it seems the issue here is rather that the character is not hidden properly, or even that it's replaced with an object.
Regarding hiding, how do you currently do that, are you changing their view to something that contains empty sprites? Note there are several methods of hiding them, e.g. they may be moved outside of the room bounds, or have their Transparency set to 100.
Finally, what is the reason to replace character with an object? Characters are superior to an object, they can do everything that object does. It's likely there's a way to make character do what you need without replacing them.

Quote from: Peegee on Mon 11/10/2021 14:57:25
3- When I load a level, if I start playing and load it again, I notice that it does not reset it. Is there a way for this or should I set the loading code to zero all items? I have very rich levels and dozens of variables.

1. AGS rooms may be state-saving and non-state-saving. Currently this is chosen only by its number: room numbers 1-300 are saving their states, and room numbers above 300 are not.
You choose the room number when creating them, and also may change them anytime by editing their "Number" property while in the editor.
2. If you want to reset the room state only in particular case, there's ResetRoom script function. Note that it will only reset objects and variables belonging to that room, if you want to reset also global variables and characters, you would have to do so by hand.

Peegee

Hello, thanks for your reply.
  I still don't quite understand the GUI part. I learned this software thanks to a brilliant girl (author of Chaelle) who showed me everything, but the GUI remains mysterious, in any case I would not have done it just with the instructions.

Thank you for all those informations. Character.SetIdleView can be efficient, and change transparency too. Currently I'm using an empty spride view, it's not that great.

I sometimes replace the character with an object:
1- Because I can change its depth.
2- Because I couldn't figure out how to move it instantly.

In my loading page, it will actually be easier to create a "button" with an object. But I couldn't find the code to load the level.

So 2 questions:
How to move the character instantly?
What code to load a level, and have it reset each time?

Thanks in advance. PG

Crimson Wizard

Quote from: Peegee on Tue 12/10/2021 07:51:40
I sometimes replace the character with an object:
1- Because I can change its depth.

Could you elaborate on this, what do you mean by "depth"?

Quote from: Peegee on Tue 12/10/2021 07:51:40
How to move the character instantly?

Characters have "x" and "y" properties, so you do simply
Code: ags

cChar1.x = 100;
cChar1.y = 200;

or
Code: ags

player.x = 100;
player.y = 200;

for simplicity if it's a player character.

Quote from: Peegee on Tue 12/10/2021 07:51:40
What code to load a level, and have it reset each time?

By "level", do you mean a room?
You load a new room using player.ChangeRoom command. You reset a room using ResetRoom command. But if you need the room to be reset every time you enter it. then simply give that room a number above 300, like I explained in my previous post.

There are also good video tutorials by densming which I usually recommend. They are a little old, but most of the things still match recent version:
Here's the link to the youtube playlist

Khris

Let me start with the easier stuff:

One of the characters is set as player character, and AGS loads a room if the player character is moved to that room. So the command to load a level is
Code: ags
  player.ChangeRoom(room_number, x, y);

Simply use a y coordinate of -1 to completely hide the player character.
Using an empty view is one way to hide them but you can simply position them outside the room's coordinate range instead.

An easy way to reset a room is to save the game in the room's before fadein event (room_Load function) and simply restore that game at the appropriate point in time (for instance when a button is clicked).

Moving a character instantly can be done by changing their .x and .y directly:
Code: ags
  cNpc.x = 123;
  cNpx.y = 45;


Not sure what you mean by depth though? Their baseline? Characters have one, too; it's at their feet but can be set manually to a different y coordinate.

As for GUIs: I remember having great respect for AGS's GUI system but the reason was primarily that I wasn't used to event based programming in general. It takes some getting used to, primarily because it means you have to keep writing functions that will be called by the engine, as opposed to writing the engine. Plus, these functions are going to run at arbitrary points in time. A good example of this is implementing key handling. The Sierra template for instance uses a bunch of GUIs, and ideally one should be able to close any of them by hitting the escape key. This is very simple with linear programming but in an event based environment all you have is a single on_key_press function that isn't tied to any GUI. Which means you need to check the state of your game, then act accordingly.
It just takes time and practice to wrap your head around this.
Although in the end, a GUI is just a rectangle hovering above your current room, and clicking a button runs a function. Creating your own quit game GUI for instance is very straightforward: the "cancel" button simply makes the GUI invisible again, and the "quit" button quits the game.

Peegee

Hello, thank you for the impeccable instant move feature!

What I meant by depth is the depth in z, the baseline for "front to back" questions. Apparently we can't change that on the characters, it's determined by the low point of the sprite. I just read your second answer, I don't see where we change that.

I can't use numbers from 300 because I have levels with multiple rooms, which don't need to be reset every time.
I redid a room load, with an object to launch room 1 with this code:
{
   ResetRoom (1);
 
player.Transparency = 0;
   cGob1.ChangeRoom (1, 129, 171);
   cGob1.FaceDirection (eDirectionDown);
   cGob2.ChangeRoom (1, 171, 166);
   cGob3.ChangeRoom (1, 89, 163);
}
(I have 3 characters) But it doesn't work, it doesn't reset when I reload the level a second time ...

Otherwise the tutorials in English are too difficult for me.

Sorry for the lines of code, I read that you have to put them a certain way but I didn't understand how.

PG

Khris

Characters have a .Baseline property you can use. Their .z coordinate is meant to do the opposite: keep their baseline at their y position while moving them up or down on the screen.

So it really depends on the situation. If your character is standing on a pedestal, you can either
a) position them at the pedestal's base coordinates, then use .z to draw them further up or
b) position them at the top of the pedestal but move down their baseline to the pedestal's base

As for resetting a room, again, save the game when the room loads, then restore the game. This is by far the easiest and most reliable way to reset your game to a previous state.

Peegee

OK, thanks. For the baseline of characters, indeed I have already modified it for a fix character, impossible to find back where is this function. But anyway, you can't change it during the game, depending on the circumstances.

I hadn't understood to save the room before. But how do you do that? I did a room load and a object thumbnail to load the room. But how to save a room and put the save in this object?

  I know that I am a heavyweight but I have no programming skills, I am just an animator graphic designer.    PG

Khris

You can change the baseline at any time during the game:
Code: ags
  cSomeguy.Baseline = 123;


As for "object thumbnail" and "put the save in this object" I have no idea what you're referring to.

What I meant is basically
Code: ags
function room_Load() {
  SaveGameSlot(101, "room x initial state");
}


To reset the room, call
Code: ags
  RestoreGameSlot(101);

in an object interaction or button's onClick function or whenever you need. This will load save game #101, effectively resetting the room.

Peegee

Hello !

Ok for the baseline, practical.

But I don't understand the Slot issue. Where is the backup going?
I have a crash when I put the SaveGameSlot function on. I am in the title page, I am trying to launch level 1:

function hSuite2_AnyClick()
{

player.Transparency=0;
  cGob1.ChangeRoom(1, 129, 171);
cGob1.FaceDirection(eDirectionDown);
  cGob2.ChangeRoom(1, 171, 166);
  cGob3.ChangeRoom(1, 89, 163);
 
  cPatate.ChangeRoom(1,246, 229);
 
aZik01.Stop();

SaveGameSlot(1, "room 1 initial state");
}

Error message:SaveGameSlot:Cannot run this command, since there was a NewRoom command already queued to run in "room101,asc, line 17

I don't understand this command, what should I do?

Peegee

#10
Ok, sorry, it works better if I put it in the right place, in the room load of room 1.

Yes, it's starting to work better. The problem is complicated by the fact that I have 3 player characters. In any case, thank you for your patience. PG

Khris

Changing the player character's room doesn't happen immediately, the command gets queued. The rest of the function runs, then AGS switches to the new room and runs its room_Load(), or whatever the "enters room before fadein" event is linked to.

This is why I deliberately put the SaveGameSlot command inside room_Load in my example code.

The error message is trying to tell you exactly what the problem is: saving a game should happen at a point where the game is idling, waiting for input. You're trying to save "during" a room transition.

room_Load is also the perfect spot to initialize your room, so move all relevant commands there.
Like this:

Code: ags
function hSuite2_AnyClick() {
  // stop music and load room #1
  aZik01.Stop();
  player.ChangeRoom(1, 246, 229);
}


Now set up the room's initial state and queue saving it
Code: ags
function room_Load() {

  // hide player character
  player.Transparency = 0;

  // position other characters in current room
  cGob1.ChangeRoom(player.Room, 129, 171, eDirectionDown);
  cGob2.ChangeRoom(player.Room, 171, 166);
  cGob3.ChangeRoom(player.Room, 89, 163);

  SaveGameSlot(1, "room 1 initial state");

}

Peegee

#12
To tell the truth I'm regressing ... He can no longer launch level 1, I have a black screen, and no error message ...



I understood the black screen ... I could not have player.ChangeRoom in hSuite2-any click AND cGob1.ChangeRoom in Room_load.
I have to put it only in hSuite2.

In any case it seems to work! Thanks a lot !!!   :-D       PG

Khris

Please try to post relevant code.
room_Load runs before the screen fades in, so my guess is you put something in there which blocks the game.

Peegee

Hello, in fact it's always a hassle. He cannot reset the level properly, he cannot reset non-player characters. When I select one of the other two characters to go loader, it's worse.

Here is what there is at the loading level:

function oDec01_Interact()
{
  ResetRoom(1);
 
cGob1.Transparency=0;
cGob2.Transparency=0;
cGob3.Transparency=0;
  cGob1.ChangeRoom(1, 129, 171);
  cGob1.FaceDirection(eDirectionDown);
  cGob2.ChangeRoom(1, 171, 166);
    cGob1.FaceDirection(eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163);
    cGob1.FaceDirection(eDirectionDown);
  cGob1.Clickable=true;
   cGob2.Clickable=true;
    cGob3.Clickable=true;
}


Here is the room load, I put a variable to save only at the first entry in the level:


function room_Load()
{
if (Dec1one==false)
{
RemoveWalkableArea(2);
oFleur2.Clickable=false;


  cGob2.ChangeRoom(1, 171, 166, eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163, eDirectionDown);
 
cPatate.ChangeRoom(1,246, 229);
cGamin1.ChangeRoom(1, 134, 431);

   SaveGameSlot(1, "room 1 initial state");
   
   Dec1one=true;
   
   if (player==cGob2)
   
{
     cGob1.Transparency=0;
cGob2.Transparency=0;
cGob3.Transparency=0;
 
  cGob2.ChangeRoom(1, 171, 166);
    cGob1.FaceDirection(eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163);
    cGob1.FaceDirection(eDirectionDown);
  cGob1.SetAsPlayer();
 
  cGob1.ChangeRoom(1, 129, 171);
  cGob1.FaceDirection(eDirectionDown);
}
  if (player==cGob3)
   
{
     cGob1.Transparency=0;
cGob2.Transparency=0;
cGob3.Transparency=0;

  cGob2.ChangeRoom(1, 171, 166);
    cGob1.FaceDirection(eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163);
    cGob1.FaceDirection(eDirectionDown);
  cGob1.SetAsPlayer();
 
   cGob1.ChangeRoom(1, 129, 171);
  cGob1.FaceDirection(eDirectionDown);
}
}
else if (Dec1one==true)
{
RemoveWalkableArea(2);
oFleur2.Clickable=false;


  cGob2.ChangeRoom(1, 171, 166, eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163, eDirectionDown);
 
cPatate.ChangeRoom(1,246, 229);
  cGamin1.ChangeRoom(1, 134, 431);
   
   if (player==cGob2)
   
{
     cGob1.Transparency=0;
cGob2.Transparency=0;
cGob3.Transparency=0;
 
  cGob2.ChangeRoom(1, 171, 166);
    cGob1.FaceDirection(eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163);
    cGob1.FaceDirection(eDirectionDown);
  cGob1.SetAsPlayer();
 
  cGob1.ChangeRoom(1, 129, 171);
  cGob1.FaceDirection(eDirectionDown);
}
  if (player==cGob3)
   
{
     cGob1.Transparency=0;
cGob2.Transparency=0;
cGob3.Transparency=0;

  cGob2.ChangeRoom(1, 171, 166);
    cGob1.FaceDirection(eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163);
    cGob1.FaceDirection(eDirectionDown);
  cGob1.SetAsPlayer();
 
   cGob1.ChangeRoom(1, 129, 171);
  cGob1.FaceDirection(eDirectionDown);
}
}
}

Cassiebsg

Who's the player character?

Also, Khris already said that SaveGameSlot(1, "room 1 initial state"); runs last, so it should be the last line in your code.

You have a bunch of  cGob1.SetAsPlayer(); and  cGob1.ChangeRoom(1, 129, 171); after your save code. Since both run at the end of the function, you again have a conflict. And I think FaceCharacter is a block action. (you can set the direction the character should face inside the ChangeRoom).

There are those who believe that life here began out there...

Peegee

Hello, in fact I have the 3 characters which are playable. So when I go to my load page, I don't know which one is playable, I put the 3 in transparent and not clickable.

  I will try to put the savegameslot last but I have a guy doing something at the very beginning, so I have to put it back every time ...

I will put the faceCharacter in the changeRoom. I'll keep you posted.

Peegee

Here is the simplified version of my room load. The variable is present so that it only saves the first time. Below is the code to start the backup. I don't have a conflict, if I don't put the ChangeRoom back, it won't start the reload. Currently, the movements between level 1 and the load page work, regardless of the character selected. The problem is always that he doesn't reinitialize the characters ...

RoomLoad:

function room_Load()
{
  if (Dec1one==false)
{
  RemoveWalkableArea(2);
  oFleur2.Clickable=false;


  cGob2.ChangeRoom(1, 171, 166, eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163, eDirectionDown);
 
  cPatate.ChangeRoom(1,246, 229);
  cGamin1.ChangeRoom(1, 134, 431);

  Dec1one=true;

  SaveGameSlot(1, "room 1 initial state");
   

}
else if (Dec1one==true)
{
   RemoveWalkableArea(2);
   oFleur2.Clickable=false;

   cGob2.ChangeRoom(1, 171, 166, eDirectionDown);
   cGob3.ChangeRoom(1, 89, 163, eDirectionDown);
 
  cPatate.ChangeRoom(1,246, 229);
  cGamin1.ChangeRoom(1, 134, 431);
   
}
}

Load:

function oDec01_Interact()
{
  ResetRoom(1);
 
  cGob1.SetAsPlayer();
 
  cGob1.Transparency=0;
  cGob2.Transparency=0;
  cGob3.Transparency=0;
 
  cGob1.ChangeRoom(1, 129, 171, eDirectionDown);
  cGob2.ChangeRoom(1, 171, 166, eDirectionDown);
  cGob3.ChangeRoom(1, 89, 163, eDirectionDown);

   cGob1.Clickable=true;
   cGob2.Clickable=true;
   cGob3.Clickable=true;


}

Cassiebsg

If you only want to save the first time, you could try adding the save to First time player enters room function.
I'm not sure where you are coming from before you start the room (another room?). If you have another room to start the game and have the start menu, then you can just select all those Goblings and player character in the start menu room, and then you can safely save when you start the new room.

"NOTE: You cannot reset the current room (i.e. the room that the player is in)."

So if you already are in room 1, you can't reset it. Meaning that you do need to be in another room to run the Reset.

>> cGob1.ChangeRoom(1, 129, 171, eDirectionDown);

Since you have set cGob1 to be the player character before, this line should be last in your code. It doesn't really affect the way you wrote it, because AGS will still run it last, but for understanding what is happening and how the code is run, you should always write the code in the correct running order, so you don't have surprises later on when the game doesn't run the way you expect it to.

Image now if AGS didn't run this line last and run it in the order your wrote it... the moment this line was executed the player would change rooms and thus all lines afterwards would not be run. And you would be wondering where the other 2 goblins were and why you couldn't click on the one you did have.
There are those who believe that life here began out there...

Crimson Wizard

Quote from: Peegee on Sat 16/10/2021 08:49:35
Hello, in fact I have the 3 characters which are playable. So when I go to my load page, I don't know which one is playable, I put the 3 in transparent and not clickable.

AGS has a "player" word, which refers to the current player character. So, when you write a generic code that may be used for any character, you just do, for example:
Code: ags

player.Transparency=0;

SMF spam blocked by CleanTalk