Help to create a small puzzle

Started by Mystère Poe, Sun 13/07/2025 09:53:35

Previous topic - Next topic

Mystère Poe

(Sorry for my english, i'm french)
Hi. I'm new to AGS and I need help understanding how to code a simple puzzle involving a glass that needs to be filled with water.
It's a fairly classic puzzle found in many games.
You have three glasses: 12 - 7 - 5.
You start with glass 12 filled, and by emptying the glasses into each other, you try to get 6.

Once you have 6, the puzzle is validated, and you move to another room. (See attached image)
Image: https://ibb.co/VpYVHbtC

I think you need to use a scoring system or something, but I don't know how to set that up.

Example: Empty glass 7 into glass 5. Make glass 5 full, leaving 2 remaining in glass 7.

I don't know if I made myself clear.

I'm French. Thank you for your help.


Mystère Poe

#1

Barn Owl

Hi Mystère Poe, bienvenue!

I am a beginner as well, so there is probably a more efficient way of doing this... But here is one way...

Create your sprites, labeled something like Xof12.gif, Xof7.gif, Xof5.gif. So you have 27 sprites labeled accordingly. Add them to the puzzle room as objects, all them visible set to except o12of12.gif, o0of7.gif, and o0of5.gif. Also create 24 inventory objects (since you won't need the empty ones, there will be fewer.)

When you interact with o12of12, script 

o12of12.Visible=false;
cEgo.ActiveInventory = i12of12;

Then both o0of7 and o0if 5, use inventory on

if (cEgo.ActiveInventory == o12of12)
{
  cEgo.ActiveInventory = o5of7; //if used on the 7 container
  o0of7.visiable=false;
  o7of7.visible=true;
}

and so on.

I'll be the first to say there are probably much better ways of doing this. But that would technically do it.

Maybe add a global variable so after too many moves the player just starts over, rather than scripting every possibility.

Anyhow, that's one way.

Happy learning and creating!


Crimson Wizard

#3
Quote from: Barn Owl on Mon 14/07/2025 01:54:50Create your sprites, labeled something like Xof12.gif, Xof7.gif, Xof5.gif. So you have 27 sprites labeled accordingly. Add them to the puzzle room as objects, all them visible set to except o12of12.gif, o0of7.gif, and o0of5.gif. Also create 24 inventory objects (since you won't need the empty ones, there will be fewer.)

There's no real need to make 27 sprites, and definitely no need to have 24 inventory objects.

First, an object on screen may be combined of just a few sprites in any combination.
Second, inventory items may have their graphic and description changed dynamically, so even if you like to keep all 3 glasses in inventory then you need 3 items at most. The water level in a glass may be set and read using Custom Properties. You add a integer property called "water level" to inventory, and then it's pure arithmetic when you use one item on another.
I did not understand whether the OP wants to have them in inventory at all though, that has to be clarified.

About combining an object from multiple sprites. Try imagining how you break an object into parts. If you are experienced with graphical software then think about graphical layers. If not, think about paper cut outs which you may stick to each other.

A glass with the water is 2 parts: 1) an empty glass shape and 2) a water inside. So you need 2 sprites to represent a glass with any water level. Maybe you don't even need a water sprite since you can use a color to paint water. Of course you may use more sprites for a glass, for example, if you want to cover water with a half-transparent glass side. But that's details. It's up for the game author to define how it should look like. Anything is possible.

How to combine sprites on screen, so that you don't see unnecessary parts of a water sprite, beyond glass's edges?

There are 3 general ways.

METHOD 1. Use either a 3rd sprite with cut from a background image, surrounding the glass, or a walk-behind. Then arrange them in layers, ordered from bottom to top (or from distant to close, for the player's perspective).

- The water is the lowest layer. Place it with some offset relative to the glass's position, depending on the wanted water level.
- The surrounding background is the middle layer. It will cover the excess of a water sprite.
- The empty glass shape is the top layer.

METHOD 2. Have several sprites per a water "step". This way you don't have to bother with cutting excess water.
Glass is one sprite, and water is constructed from N steps. These steps may be each separate sprites, or just using a single "step" sprite, depending on the shape of the glass. But you have to use several objects: 12 objects for a glass with 12 levels, 7 objects for a glass with 7 levels, and so on.

This method requires much more objects than method 1, but may be easier to setup a scene in some circumstances.
Also, if you are okay to do bit more scripting, then you may use "room overlays" instead of objects, as overlays are created and deleted dynamically, and there's no limit of them.

METHOD 3. Dynamic sprites. That may sound scary at first, because it requires more scripting, but with dynamic sprites you may create a mix of virtually any number of sprites on a single sprite, and then assign the resulting sprite to the single object.

I think for the glass with the water the order of operations should be following:

- create an empty fully transparent dynamic sprite.
- either paint a water sprite with some offset (depends on water level), or fill part of the sprite with the water color.
- have a sprite with a fully opaque glass shape, and use function CopyTransparencyMask to copy surrounding transparency to the final sprite. That will cut out any excess of painted water.
- finally paint a glass's shape which lets see water inside.


While METHOD 1 and 2 can be used for room objects, they cannot be used for inventory items (at least not with default AGS inventory). So METHOD 3 suits inventory items more.


On another hand, there are ways to simplify things. For example, you may use, say, only 3 variants of sprites for inventory item: empty glass, half-filled glass, and fully filled glass. That will let you use METHOD 1/2 for glasses in the room, and a simple solution for the glasses in inventory.

Khris

#4
Regarding the math side of things, here's how to code this:

Code: ags
int size[3], level[3]; // three glasses: [0] is the size 12 glass, [1] is the size 7 glass and [2] is the size 5 glass

  // when puzzle starts
  size[0] = 12;
  size[1] = 7;
  size[2] = 5;
  level[0] = 12;
  UpdateGlasses(); // call helper function that draws the glasses

Next we need a function that handles pouring water from glass A to glass B:

Code: ags
function Pour(int from, int to) { // from, to = 0, 1 or 2
  if (from == to || from < 0 || from > 2 || to < 0 || to > 2) return; // prevent errors
  int space = size[to] - level[to]; // how much space is in the target glass
  // transfer either space or level[from] units, depending which is less
  int transferred = (level[from] > space) * space + (level[from] <= space) * level[from];
  // do the actual transfer
  level[from] -= transferred;
  level[to] += transferred;
  UpdateGlasses();
}

Now all you need to do is call Pour(0, 2); to handle the player pouring from the 12 glass to the 5 glass.

Mystère Poe

Ok  ;)  I see. I will try this this weekend. THANKS .

Eon_Star

I could make a tutorial on that topic. Good puzzle advice. Thanks.

SMF spam blocked by CleanTalk