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 - Crimson Wizard

#361
Quote from: Mehrdad on Sat 29/03/2025 14:16:13OK. It's the same "mouse release" think so and I'm sorry that I don't know your complete API

The existing touch API is listed in the first post here.

Quote from: Mehrdad on Sat 29/03/2025 14:16:13My mean was add more examples to this demo. Like holding two fingers at the same time to run fast or shoot a bullet, etc.

I'd rather prefer users try this out and make their own tests and demonstrations. That will also show if the api is easy to use and understand. If you have questions about how to script something particular then I can answer them here. If we find that something is missing, then we can make additions to API.
#362
@arj0n there was a bug in the engine , a temporary fixed version may be downloaded here:
https://cirrus-ci.com/task/4805609725362176
#363
Advanced Technical Forum / Re: RAM limitations
Sat 29/03/2025 20:32:41
Quote from: lafouine88 on Sat 29/03/2025 20:03:43I don't think there is any magical solution here, so unless there is a magical solution to expend the RAM limit

There's an opportunity to use the 64-bit engine version, which supports much higher ram cap (as much a computers can have today). But that will still mean that your game will require that much, which may not be a good thing.

I'd suggest to reduce sprite sizes as much as you can to still accommodate the pieces of equipment. That will of course make setting things up less convenient: you will have to script a system of offsets which each part should have relative to the main body. But this also may have a significant positive effect on memory requirements.
#364
Quote from: Mehrdad on Sat 29/03/2025 12:40:451) For point & click adventure games we needed to "release mouse" instead of "left click". Because we want to search the room for find objects and hotspots by touching them without moving the player to the point.

2)Add  D-Pad instead of a joystick too (Up, Down, Left, Right) and combine

3) Combine two touches for an action like running

I'm sorry because I may be misunderstanding, are you proposing to change the demo game, or add something to the touch api?

Touch API has separate "pointer down" and "pointer_up" events, so it's possible to do something when the finger is pressed, and when it is released.
It in theory lets you to track as many fingers as the device supports, up to 10 (I think).

Or were you suggesting similar events for the mouse too?
#365
Quote from: Snarky on Sat 29/03/2025 13:09:38I think the basic idea of getting rid of AudioChannel in favor of something tied to the playback instance, and guaranteed to be non-null, is probably the right approach.

Not ready to give a full reply right now, just couple of quick notes.
I am not certain about getting rid of AudioChannel is a good thing or not. It may be a good thing to not have a channel as a return value from Play(), but at the same time I found audio channels to be an interesting logical concept in how multiple simultaneous playbacks are organized.

In regards to a "null pointer" problem, there's something that hit me recently, and I wonder why did not I think about this earlier. What if Play() returned a dummy audio playback? There are 2 reasons for Play to fail: failure to decode and failure to play, the former happens when the file cannot be opened at all, and the latter when the sound device is not working, or game set to use "no driver".
We are mostly interested to prevent script errors in the second case, because the first case will be noticed immediately during the game development. In audio software that works with filter chains there's a concept of "null" output, where the processed sound is simply discarded. So what we could do is to process the sound internally (which will even update its Position property), but then discard it through such "null" output. I did not check yet, but it's possible that our sound library supports that already.
#366
Quote from: qinzha on Fri 21/03/2025 10:05:33The thing is, that the video seems to get slower, not faster and the audio sounds fine to me :S

Sorry for now replying earlier. I don't really know what to say based on this information. There are two possibilities here: either AGS does not decode the video properly, or it fails to play it with proper speed because things go slowly for some reason.

Could you tell which resolution your game and your video are, and maybe you could upload your video somewhere to let me check it out? (You can PM me the link if you don't want to post it in public)
#367
Advanced Technical Forum / Re: RAM limitations
Sat 29/03/2025 09:55:10
First of all, I do believe that this should have been posted in "Advanced Tech Forums", because it's not a basic question, and the topic should have a more specific title, because "ram limitations" is just way too abstract.



But, speaking on the topic...

The peculiarity of 2D sprite-based games is that you need separate sprites for all directions and movement frames, and because of that their numbers may grow exponentially.

Compare this with 3D games where you use textures and models: a single texture may be displayed from all sides because it's calculated in real-time. Animations are done by changing model pose, but texture is skinned on any pose automatically. Shaders allow to change the looks further dynamically using pure math (without an extra set of images). This may seem paradoxical, but 3D games often require much less resources to load to display same thing (at a cost of more processing done by gfx card).
That is why, in the contemporary game making, it may be more suitable to make such games, as you described above, in the 3D engines or 2D engines which use skinned models, rather than sprite-based engines.

I know nothing of what your game has in it, so it's difficult to give precise advises.
But if you want to stick to 2D engine and use sprites, then you need to know that such game may be only kept under reasonable memory limit if it's either done in low-resolution, or it has limited amount of variants of "skins", OR it has a efficient resource management, where you keep only limited number of things in memory at a time. Or, better, all the above at once.

For example, if I remember correctly, the first episodes of Diablo series (1,2) were sprite based, but did not have a separate "body" sprite for literally every unique item, instead they had separate sprites per a "class" of an item, like: a small shield, a big shield, a sword, a mace etc. So a player could change from e.g. "weak sword" to a "stronger sword", but the character on map would still display same sword sprite.

In regards to resource management, I don't know how you do that now. I vaguely remember our past conversations, but I don't remember how they went and which solution did you choose in the end.
I assume that you are using "paper doll" technique, where you gather your character from multiple pieces, either by applying to their frames or by having separate character or overlay for a piece, following the main body.
Assuming that's right, why do you need to load all possible armor pieces into memory, when you only need them to display on your character? Do you keep them or most of them in memory in case player changes the outfit? How do you do that? I suppose that I'd try to limit the number of stuff loaded, and only keep things that player has in inventory, or even only things that he/she was wearing very recently; and load anything else only when necessary.

There are other considerations here, such as size of armor sprites. How these are done, why do they take so much mem? What is your game resolution, and your item resolutions? You've mentioned "256*256" sprites, not sure what that is exactly. Are you saying that each piece of armor is drawn as a full-body size transparent sprite with armor piece somewhere in the middle, instead of a smaller sprite to only fit the armor piece itself? Can you post some examples?

Another thing, you say that you are preparing everything as dynamic sprites. Which means that you likely have less use for the default engine's sprite cache. Which size do you have set for the sprite cache in the game config?
#368
So how this can be solved in the engine, in the short term at least?

Suppose I add a game-wide setting that tells which mouse button should gui controls react to? Where 0 would mean "any" (compatible default) and mouse button code will restrict their reaction to that button.

Generic events such as eEventGUIMouseDown and eEventGUIMouseUp will run always.
#369
Please clarify which is your intent, because it's not just pushed image, the buttons will actually run their action on either click, left or right. Is that okay with you, and you just want to not have it show pushed image with the right click? Or do you want the button to not trigger on right click at all?

I don't think there's any setting that will disable button reacting to a right click. But you don't need 2 buttons for a workaround, you may use 1 button without a PushedImage, and change its image temporarily following the left mouse down. I suppose this may be scripted globally for multiple or all buttons in the game.

That sounds like an annoying necessity though. I wonder if that's a design oversight in this engine, and how come there are not many requests like this...
EDIT: i think even middle click triggers gui buttons.
EDIT: and not only buttons, but other controls react to right click too: such as sliders and list boxes.
#370
Quote from: Eon_Star on Sat 22/03/2025 17:26:06It may be because I use the 360 and 361 versions. Some of the functions have being changed.

I've posted this earlier in this thread, but may repeat:

3.6.* versions are fully backwards compatible, and ALL the old commands may be enabled again by changing the "Script compatibility level" in General Settings -> Backwards Compatibility; as well as few other settings, as explained here:
https://adventuregamestudio.github.io/ags-manual/GeneralSettings.html#backwards-compatibility

Alternatively, here's the list of deprecated commands and their new equivalents, this table may be used to fix the script yourself:
https://adventuregamestudio.github.io/ags-manual/ObsoleteScriptAPI.html
#371
Quote from: Nowhere Girl on Fri 21/03/2025 20:53:42combined screenshot of game folder contents

From the look if it, the game's exe "Qfg2vga.exe" has size 0 bytes. Also, in the version that I have on my computer there are Qfg2vga.010 and Qfg2vga.011 which are not present in your folder.

I suggest the game got corrupted somehow. Perhaps try reinstalling it?
#372
Erm... which files do you have there in that folder exactly?

Can you make a screenshot of the folder contents?

EDIT: also, just in case, what version of AGS have you downloaded? For instance, AGS 4.0 does no longer support old games.
#373
Quote from: Nowhere Girl on Fri 21/03/2025 19:55:13Supposedly it can work with the following roundabout: download AGS, take the file acwin.exe, put it in the game folder and use it instead of the proper game executable. It didn't work. First I got the message: "Executing code cannot be continued, because SDL2.dll object was not found. Reinstalling the program could solve this issue". I downloaded the SDL2.dll file and placed it in the game folder too and now I get another error message: "Application was not properly launched (0xc000007b). Click OK to abort the application".

You can take SDL2.dll from the same AGS package, it should be there along with acwin.exe.
If you download it from SDL2 webpage, then it must match the acwin.exe's bitness, meaning it has to be a 32-bit dll (may also have "x86" in the archive name).

Can't say anything about ScummVM, not an expert in how it works or which AGS games supports.
#374
I looked at the Tumbleweed's source and, unfortunately, the change I suggested to array won't work directly, as VerbGuiUnhandled is not a real array, but a "indexed property". Regardless of the chosen approach more changes would be required for the module to make this work.

I would have to find spare time and write a answer with a proper solution, unless someone else does this first.
#375
Your mistake is that you run the randomization only once the game starts, save its result in array, and then it will be used all time after.

If you want a random reply each time, then you should get rid of "VerbGuiUnhandled" array completely, and call respective GetRandomxxxResponse instead whenever that array was read in the template code.

I don't remember the template's code. Maybe you could write a wrapper function GetRandomResponse(int unhandled_verb_type) for convenience:
Code: ags
String GetRandomResponse(int unhandled_verb_type)
{
     switch (unhandled_verb_type)
     {
     case eVerbGuiUnhandledUse: return GetRandomUseResponse();
     case eVerbGuiUnhandledLook: return GetRandomLookResponse();
     // etc
     }
     return "respond in case of unknown type";
}

Then whenever the template had something like:
Code: ags
String s = Verbs.VerbGuiUnhandled[ verb_type ];
you replace that with:
Code: ags
String s = GetRandomResponse( verb_type );



EDIT:
An alternative way would be to make a 2D array, where you can store multiple responses per unhandled verb type. Then a user would configure the array in template settings, filling it with all possible variants of reply, and Verb module would run a Random function to choose from these.
AGS 3.* does not support multidimensional arrays, but it's possible to either emulate 2D array using 1D array (although it may be complicated in case there are varied number of responses per type). Or this may be done by introducing a struct with array inside, like:

Code: ags
#define MAX_RESPONSES 8
struct UnhandledVerbResponse
{
     String Responses[MAX_RESPONSES];
     int ValidResponsesCount;
};
and change VerbGuiUnhandled to hold these structs instead of plain strings:
Code: ags
// making this up, cause I don't have a template declaration before me right now
UnhandledVerbResponse VerbGuiUnhandled[max unhandled events];
#376
First of all please clarify: does it play fine when you open it by a video player program?
In other words is the problem in video or in how AGS plays it?

Then, how does AGS compare to the external video player? Does the image run same speed and sound becomes slower, or does the sound run same speed and frame changes become faster?

One known issue is that the video player in ags skips "black frames". This is mentioned in the two older conversations:
https://www.adventuregamestudio.co.uk/forums/beginners-technical-questions/how-play-two-videos-one-right-after-the-other/msg636661268/#msg636661268
https://www.adventuregamestudio.co.uk/forums/advanced-technical-forum/problems-with-ogv-video/
#377
QuoteSince you can change properties of objects, characters and hotspots that are not in the currently loaded room

You are mistaken, AGS does not let you change anything in the unloaded room (room objects and hotspots).
Characters do not belong to the room, even though they may be "placed" in one, they are considered global objects.

In regards to the memory management:


Global objects (game settings, characters, guis, etc) are loaded once while the game is loaded. Their data is just their properties, not graphics. Graphics are loaded separately.

Compiled script modules are loaded once the game is loaded and kept in memory at all times as well.

Room data is loaded once a new room is entered. Room data is separated onto a saved and not saved part, where saved part remain in memory after room is exited and re-applied when you return to that room. The exception is "non-state-saving" rooms (ones with number 301 and higher) - these are never kept in memory after leaving them.
The part which is saved is object and hotspot states (enabled/disabled, assigned object image numbers, etc), but also values of all the room variables found in room script.

Compiled room scripts themselves are only loaded during the room, and unloaded after.

In the big games with large amount of global objects and large amount of visited rooms the accumulated amount of object data can become significant, but still not as big in relative terms. We are speaking maybe megabytes or few tens of megabytes top in extreme cases.

What can make the memory consumption actually big is:
1. Loaded graphics.
2. Allocated dynamic objects (ones created by a script command).

Graphics: AGS engine uses a "sprite cache" mechanism that streams sprites on demand and saves for the future. In practice "by demand" means "when they need to be displayed". Also, in the latest versions of AGS you can request to precache particular sprites by a script command.
The size of the sprite cache is limited by a config setting (you can see that in setup program too). Normally it will never go over this limit. The sprite cache keeps a history of sprite uses (known as "MRU list"). Whenever a new sprite has to be loaded while the sprite cache is already filled to the top - it unloads some sprites to free the space, starting with the sprites that were not used recently. In a regular situation this ensures that sprites and animations that are used often are kept all the time, and sprites that are used occasionally are getting replaced. (Of course there are edge cases, especially if the game requires too many new sprites at once.)

Besides normal sprites that are loaded automatically as described above, there are also Dynamic Sprites. These are fully managed by the game script (which you write), and are not counted towards the sprite cache limit. They are deleted only when you tell it to.

Finally, there are dynamic script allocations: dynamic arrays and managed struct instances. AGS has a single global "managed object pool" where these objects are kept, and they never get freed unless deleted by a script. It does not matter where such object was created: in a global script or a room script, it stays until deleted by a script (even if room in which script it was created in is unloaded).

EDIT:
Audio: engine has a rule according to which it may load an audio clip at once if it's small enough (couple of megs iirc). All the other clips are streamed, meaning they are opened from disk and read piece by piece as playback goes further.
There's a sound cache, but unlike the sprite cache it has a small size by default, and it's meant for small clips only (there's a config setting that tells the max size of a clip which may be put there). Larger clips are normally not kept in memory and are discarded after playing.

Videos are streamed, and never kept in memory after playback finishes.
#378
Quote from: Barn Owl on Wed 19/03/2025 05:03:07The player would rather click-to-stop the function than proceed. Something like SkipAnyKeyOrMouse, yet for the function in eBlock progress. Is there any quick script I'm missing to stop a function during an eBlock?

You would have to write your own interruption handling, because not only you need to be able to stop a blocking action, but also:
1. You need to distinguish when this is allowed and when not;
2. You need to check the result after the walk is complete and proceed or cancel the sequence depending on that result.

I added the script example to my post, but that's essentially a simplified version of what is inside of these modules.
#379
I presume that this is about a interaction sequence and not a regular walk, and you have other commands that depend on the walk's outcome.

The idea in a nutshell is this: you need a custom walk function that will start a non-blocking walk and run a waiting loop while the character is moving, and also repeatedly check for the key or mouse presses using IsKeyDown and/or Mouse.IsButtonDown. This function should also return a boolean value, telling whether the walk was complete or interrupted by player.

In a very primitive sense, it may look like this:
Code: ags
bool MyWalk(Character *c, int x, int y, WalkWhere where)
{
     c.Walk(x, y, eNoBlock, where);
     bool was_interrupted = false;
     while (c.Moving && !was_interrupted )
     {
           Wait(1);
           if (Mouse.IsButtonDown(eMouseLeft))
                was_interrupted = true;
     }
     return was_interrupted;
}
and then used like this:
Code: ags
if (!MyWalk(player, .....))
    return; // was interrupted, don't continue the sequence

There are already couple of modules that do this sort of interruption and report result. You may try using them, if you don't want to write your own code for this:
https://www.adventuregamestudio.co.uk/forums/modules-plugins-tools/module-cancellablewalk-1-0/
https://www.adventuregamestudio.co.uk/forums/modules-plugins-tools/module-gotthere-0-5/

EDIT: Above is the easiest solution to do, but it has its limits. The biggest one is that the player won't be able to interact with anything else, nor open a menu, or save/restore the game, etc. If that's not needed, then above solution will work fine.
On another hand, if you need a way to sequence some actions, and run them non-blocking, so that player could still work with GUIs at the same time, then the solution has to be largerly different. But I will skip that until this question is cleared.
#380
There's something that I'd like to say... Programming has two concepts: "scalability" and "reusability". In very simple words "scalability" means: how the solution behaves when the amount of data increases? and "reusability" naturally means if it's possible to use same code for many different variants of a task.

Your original code uses "switches" and does a separate check for each possible combination one by one. You say it requires 1500 lines, and that's just 3x3 puzzle. Imagine some time later you decide to make 5x5 puzzle, how much more lines will it take?
At the same time the variant of the code that uses arrays and "for" loops will increase only in the place where you initialize the board, but the main part will remain the same. That's because it handles each cell using same piece of code. And with a small number of changes it will be possible to adjust this code so that it can be used in any board size combination, any screen resolution, etc, so same code may be run from multiple puzzle rooms for example.

You may use any code you prefer of course, but I strongly recommend learning to write the variant with array and for loop whenever you have spare time. Learning efficient ways of coding takes time now but saves a huge amount of time later. Plus your program becomes compact, and compact programs are (usually) working faster and easier to fix in case of a mistake.
SMF spam blocked by CleanTalk