Trying out MonoAGS (AGS 5 candidate) : journal

Started by Monsieur OUXX, Wed 02/05/2018 14:56:42

Previous topic - Next topic

Monsieur OUXX

#20
Quote from: tzachs on Thu 03/05/2018 22:00:37
Are you using Escoria?
If you recall the thread where I was trying to compare the engines, that one was my teacher's pet. But I need to be realistic : If I ever want to have a chance to complete the game I'm working on, I need to stay somewhere where there's a community that knows shit ;)


EDIT : moving on. So now the game compiles (even without Xamarin -- that said, I didn't pay attention to the .Android project, it might just be that it's been excluded automatically  from the build the first time it failed to load/build).
The game runs.
I'm running Demo Quest, and I'm worried about two things : 1) the mixed resolutions (game in low-res, font in hi-res, and I couldn't see if the cursor is aligned to the low-res grid or to the screen's resolution), 2) building the animations (views/loops). Without a GUI, it will be a real pain! For me that's a big no no.
 

tzachs

Quote from: Monsieur OUXX on Thu 03/05/2018 22:45:20
the mixed resolutions (game in low-res, font in hi-res,
You can turn off the hi-res fonts, just delete the lines: "GLText.TextResolutionFactorX = 4; GLText.TextResolutionFactorY = 4;" in Program.cs.

Quote
and I couldn't see if the cursor is aligned to the low-res grid or to the screen's resolution)
Everything is done with sub-pixel positioning so the cursor should align with the screen's resolution. If aligning the cursor the the low-res grid is important, it shouldn't be too hard to add as a feature (though if you couldn't tell the difference, who will?).

Quote
2) building the animations (views/loops). Without a GUI, it will be a real pain! For me that's a big no no.
I agree, an animation editor is a must for version 0.1.
Note though that for loading the animation loops, you can load an entire folder as a loop without having to write every single frame path (assuming the frames are alphabetically ordered).
In fact, loading idle + walking animation for the hero in the demo game is done with this single expression:

Code: csharp

IOutfit outfit = await game.Factory.Outfit.LoadOutfitFromFoldersAsync(_baseFolder, walkLeftFolder: "Walk/left",
	walkDownFolder: "Walk/front", idleLeftFolder: "Idle/left", idleDownFolder: "Idle/front", 
	speakLeftFolder: "Talk", loadConfig: loadConfig);

Monsieur OUXX

@Crimson Wizard or others : how ae sprite resources loaded in AGS? For example, will the loop sprites of a view be loaded when I set the view to the character? Will the objects and background sprites be loaded when I enter the room?
 

Crimson Wizard

#23
Quote from: Monsieur OUXX on Fri 04/05/2018 16:34:37
@Crimson Wizard or others : how ae sprite resources loaded in AGS? For example, will the loop sprites of a view be loaded when I set the view to the character? Will the objects and background sprites be loaded when I enter the room?

This is, among with lack of the Editor, IMHO the weakest part of MonoAGS right now. The problem is that it does not have any built-in resource manager yet.
You have to mostly write storing and loading (and freeing) stuff yourself.
Of course there are factory methods, like the LoadOutfit function quoted above, that make it possible to quickly load a whole "group" of items. But still the process has to be controlled by you.

Iirc DemoGame loads every game resource at the start.

I did not like this approach, so tried to experiment a bit, looking for a way to handle rooms resources. You may check out how I did it in latest games ("Last & Furious" and "Layers Game"). There are classes that may be called "Room managers" (DemoGame has similar thing also). E.g. check "RoomScript" class, it's a parent class of "room manager", and there is "loadAsync" method in every subclass that loads stuff - you may check their implementations to see how they load resources up.


For example, this is the room loading code from the TitleScreen of the Last&Furious:
Spoiler

Code: csharp

protected async Task<IObject> addObject(string name, string gfile, int x = 0, int y = 0)
{
            IObject o = _game.Factory.Object.GetObject(name);
            o.Image = await _game.Factory.Graphics.LoadImageAsync(_roomAssetFolder + gfile);
            o.X = x;
            o.Y = y;
            return o;
}
protected override async Task<IRoom> loadAsync()
{
//========== FROM HERE ON - we load stuff and create objects ===========================
            IGameFactory factory = _game.Factory;
            _room = factory.Room.GetRoom(ROOM_ID);
            _room.Background = await addObject("TitleScreen.BG", "gradiented-title.png", 0, -80);

            // TODO: label with the game version number in the corner of the title screen
            var label = factory.UI.GetLabel("VersionLabel", LF.GAME_VERSION, 0, 0, 0, 0, addToUi: false);
            label.TextConfig.Font = AGSGameSettings.DefaultTextFont;
            label.TextConfig.AutoFit = AutoFit.LabelShouldFitText;
            _room.Objects.Add(label);

            _room.RoomLimitsProvider = AGSRoomLimits.FromBackground;

            _music = await factory.Sound.LoadAudioClipAsync(LF.MusicAssetFolder + "Car-Theft-101.ogg");


//========== Initializing other settings and subscribing to events ===========================
            _room.Events.OnBeforeFadeIn.Subscribe(onLoad);
            _room.Events.OnAfterFadeIn.Subscribe(onAfterFadeIn);
            _room.Events.OnAfterFadeOut.Subscribe(onLeave);

//========== Rooms is done, return it ===========================
            return _room;
}

[close]


Some things may be loaded separately from the room, when they are required. I made separate loading functions for that.
For example, I have a static class RaceAssets that has a method that loads anything related to racing itself.
I call it when player chooses "Start Game", during transition into racing room:
Spoiler

Code: csharp

public static async Task LoadAll(IGame game)
{
	IGraphicsFactory f = game.Factory.Graphics;
	for (int i = 0; i < Names.Length; ++i)
	{
		string name = Names[i];
		IImage carmodel = await f.LoadImageAsync(string.Format("{0}carmodel{1}.png", ObjectAssetFolder, i + 1), MagicColor.TopLeftPixel);
		CarModels.Add(name, carmodel);
		IImage portrait = await f.LoadImageAsync(string.Format("{0}face{1}.png", UIAssetFolder, i + 1), MagicColor.TopLeftPixel);
		Drivers.Add(name, new DriverCharacter(name, portrait, carmodel, 90.0F));
	}

	RacerFrames = new IImage[Race.MAX_RACING_CARS];
	for (int i = 0; i < Race.MAX_RACING_CARS; ++i)
		RacerFrames[i] = await f.LoadImageAsync($"{UIAssetFolder}racerframe{i + 1}.png", MagicColor.TopLeftPixel);
	BannerReady = await f.LoadImageAsync(UIAssetFolder + "banner1.png", MagicColor.TopLeftPixel);
	BannerSet = await f.LoadImageAsync(UIAssetFolder + "banner2.png", MagicColor.TopLeftPixel);
	BannerGo = await f.LoadImageAsync(UIAssetFolder + "banner3.png", MagicColor.TopLeftPixel);
	BannerLoose = await f.LoadImageAsync(UIAssetFolder + "banner4.png", MagicColor.TopLeftPixel);
	BannerWin = await f.LoadImageAsync(UIAssetFolder + "banner5.png", MagicColor.TopLeftPixel);
}

[close]


Similarily, I could perhaps make mirrored methods of unloading things, which would dispose all those image objects, etc.


Observing this code, you may notice that I sometimes load sprites directly in the object. This is a okay in a tiny games, but in bigger game could cause duplication of resources in memory.

In theory you could emulate AGS sprite system by creating a List<IImage>, or Dictionary<some key type, IImage>, loading sprites there first, and then assigning that list/dictionary elements into your objects and views.

tzachs

Crimson Wizard, I believe Monsieur OUXX was asking about how sprite loading works in AGS, not how it works in MonoAGS.

Quote
This is, among with lack of the Editor, IMHO the weakest part of MonoAGS right now. The problem is that it does not have any built-in resource manager yet.
You have to mostly write storing and loading (and freeing) stuff yourself.
Right, well, from my point of view the issue of having to write the loading code yourself is because there's no editor, not because there's no resource manager. The editor will generate that code for you.

As for a resource manager, the current plan is to have a resource loading strategy and resource freeing strategy which will be built on top of the current infrastructures. So for resource loading strategy you might have "load on startup", or "load when entering room (which has the specific asset)" or "load only when the asset is needed" (lazy loading), and you'll be able to code a custom resource loading strategy which does things differently. Similarly for a resource freeing strategy you might have "free after resource was not used for X amount of time" or "free when leaving room" or "always in memory" or your custom coded freeing strategy.
And you'll have the option to set a default loading/freeing strategy for the game, and override it for specific assets.

Crimson Wizard

#25
Quote from: tzachs on Fri 04/05/2018 17:59:18
Crimson Wizard, I believe Monsieur OUXX was asking about how sprite loading works in AGS, not how it works in MonoAGS.

Um, oh.

Well, in that case
Quote from: Monsieur OUXX on Fri 04/05/2018 16:34:37
how ae sprite resources loaded in AGS? For example, will the loop sprites of a view be loaded when I set the view to the character? Will the objects and background sprites be loaded when I enter the room?

In AGS sprites are loaded in memory only when they have to be displayed on screen. AGS is constantly streaming sprites into sprite cache, keeping track of the order the sprites were demanded by the drawing code. And when the cache is full it gets rid of the sprites that were used long ago first.

Note, that this is an optimal solution for low-res games, where sprites are smaller and animations are not that long. For hi-res games with smooth animations with lots of frames pre-caching strategy could be a better choice.

Room backgrounds is an exception here, they are loaded immediately.

cat

I'm joining you playing MonoAGS but I'm already stuck ;)

I checked out the source and installed Visual Studio but I get this "The current .NET SDK does not support targeting .NET Standard 2.0. blablabla" message. I installed the .NET Core and 3.5 development tools additionally via Visual Studio Installer but I don't have the dotnet command on the command line ???
For workloads I only picked .NET desktop development in the installer.

I'm really clueless, do I have to install some additional components? Seems weird this is not done automatically when installing VS.

tzachs

Quote
I'm joining you playing MonoAGS
Great! :)

Quote
but I'm already stuck
Not so great..

Quote
but I don't have the dotnet command on the command line
Hmmm, that is weird. Were there any errors during the install?
I would check first if dotnet core was really installed: is there a "C:\Program Files\dotnet" library? what folders do you see in "c:\Program Files\dotnet\sdk" and "c:\Program Files\dotnet\shared\Microsoft.NETCore.App"?
If nothing is there, then it looks like it wasn't installed. I don't know if it's a problem in VS installer, but you can also install it from here: https://www.microsoft.com/net/learn/get-started/windows
If there is a dotnet core version installed, then maybe for some reason the installation failed to add it to your PATH environment variable.

Other than that, what time did you download MonoAGS? I pushed a fix to the original problem a few hours ago. If you downloaded before the fix make sure to delete the "global.json" file.

Crimson Wizard

I have an idea. Making proper and thorough documentation takes a while, but posting solutions in forum posts make things go unnoticed.

Monsieur OUXX, what about creating a google drive document, or any similar kind of page, and sharing permission with few people, tzachs + those who are interested trying MonoAGS. Then fill that documents with FAQ and first step instructions, that all contributors could ammend.

cat

Quote from: tzachs on Fri 04/05/2018 21:33:21
Hmmm, that is weird. Were there any errors during the install?
Not that I've noticed...
Quote
I would check first if dotnet core was really installed
Right, looks like it wasn't installed at all. No idea what the VS installer was doing :-\

I installed it from your link, and now I was able to compile it and run the demo! ;-D

tzachs

Quote from: Crimson Wizard on Fri 04/05/2018 21:41:37
I have an idea. Making proper and thorough documentation takes a while, but posting solutions in forum posts make things go unnoticed.

Monsieur OUXX, what about creating a google drive document, or any similar kind of page, and sharing permission with few people, tzachs + those who are interested trying MonoAGS. Then fill that documents with FAQ and first step instructions, that all contributors could ammend.
I created a FAQ wiki page with what was raised so far: https://tzachshabtay.github.io/MonoAGS/articles/faq.html
Note that if you have a Github account you can easily (I think) contribute changes: there's an "Improve this doc" button on the top right of the screen (and all on other pages in the website) which takes you to the page on github, from there it's just about clicking the edit button (behind the scenes I believe it automatically forks the project, and creates a pull request with the suggestions).

If that's not satisfactory, I'm ok with having a google doc.

Crimson Wizard

#31
Sorry, I did not mean extra job for you, I suggested google doc for non-developers, as something you can make quick notes in without worrying for organizing, since I noticed Monsieur OUXX is already doing similar thing in his first post...
The problem with document in repository is that other people won't know what to write there, except maybe questions.
But this was just an idea, idk if anyone find that convenient.

cat

So, I have a few questions/remarks. If you think this derails this thread too much, please tell me and I'll move it somewhere else.

  • In contrast to AGS, MonoAGS' output is .NET, right? This means, that not only developers but also players will have to have .NET installed on their PCs. Isn't this a problem? It seems that the newer Windows versions ship with .NET installed, but what about the older ones? What version would be safe for most Windows versions? I guess the engine build should target a low enough version? Any thoughts on that topic?
  • When starting the game, there are two windows opened. Why is that so?
  • Did you plan localization for games? ITranslate seems to refer to positions, not language. Adding localization support later on could be a pain in the a..
  • Why do the shaders not affect the player character?
  • Is there anything that can be actually done in the demo game?

tzachs

Quote from: cat on Sat 05/05/2018 11:11:30
In contrast to AGS, MonoAGS' output is .NET, right? This means, that not only developers but also players will have to have .NET installed on their PCs. Isn't this a problem? It seems that the newer Windows versions ship with .NET installed, but what about the older ones? What version would be safe for most Windows versions? I guess the engine build should target a low enough version? Any thoughts on that topic?
Yes, MonoAGS output is .Net, but players will not necessarily need to have .NET installed. MonoAGS currently compiles to dot net framework on windows and on mono for non-windows. The plan is to also add support for .Net Core, which is the new open source runtime sponsored by Microsoft. Both .Net Core and Mono can be packaged with the game so that the player will not need to download it, and there are linkers that strip out all parts of the framework that the game doesn't actually use, so the added hard-disk space should not be too big (this is in theory, we'll need to actually try it out to see that it works as intended).
As for old Windows version, the engine supports Windows 7 and above, Windows XP (and vista) are not supported. I wanted to support Windows XP but it's too hard:
1. It would mean targetting an older dot net version and losing out on a lot of features and cross-platforming capabilities (not to mention security fixes).
2. One by one all of the dot net libraries are killing support for Windows XP, so that will require using older versions or maintaining our own forks, not feasible for the long-term.
Otoh it's getting less and less used by the day (as of this day it has only 0.25% market share on steam) so hopefully it would not be too big of an issue.

Quote
When starting the game, there are two windows opened. Why is that so?
The console window can be turned off (somewhere in the project options iirc). I currently left it on for my development purposes (I noticed that on rare occasions, at least on Mac, it will show me errors that are not visible on the visual studio debug console), but I'll turn it off by default soon.

Quote
Did you plan localization for games? ITranslate seems to refer to positions, not language. Adding localization support later on could be a pain in the a..
Yes, I have plans for adding localization support (tracking issue is here if you have some specific thoughts). I have some vague ideas on how it will be implemented (basically thought of a partially cloned structure of the asset tree in a specific language folder -> if there is a matching translated asset we will take it, otherwise we'll take the base language asset).
I agree that it will be a big PITA to implement in a working system, but so is everything else really: i.e I had to make some hard decisions on which features to support initially and which to add later (I couldn't do all at once), and it doesn't matter what my choice is, the later a big feature is to add, the harder it gets do develop it.

Quote
Why do the shaders not affect the player character?
Currently you can set a shader for the entire game/screen and a shader for specific entities. If you set a shader for a specific entity it overrides the shader of the game, and the player has a specific shader (just for demo purposes). There is a plan to support multiple shaders per entity/screen which will then apply the screen shader to the player as well (this will probably be opt-out because you might WANT to override the screen shader).

Quote
Is there anything that can be actually done in the demo game?
Do you mean, puzzles? No.
You can look at the window in the left-most screen to see some viewport zooming, rotating and moving in parallel with some simple tweens.
You can click on the "?" button which opens a window to show a few of the features.
You can click alt+g to open the game view and the inspector and can play with all the different properties of the entities (there's a lot more to play there than with the properties window in AGS, so it's probably worth the time understanding them all, though note that the inspector is not completed yet so there are some available things you can do with the engine which you still can't do with the inspector).

Crimson Wizard

#34
Quote from: tzachs on Sat 05/05/2018 15:41:30
Yes, I have plans for adding localization support (tracking issue is here if you have some specific thoughts). I have some vague ideas on how it will be implemented (basically thought of a partially cloned structure of the asset tree in a specific language folder -> if there is a matching translated asset we will take it, otherwise we'll take the base language asset).

Probably should be posting this in the git issue... only wanted to put my little 1 cent for now. The localization system consists of two features, or two mechanics if you prefer: picking out appropriate asset, and assigning it to game object. The first is relatively easy, and my belief is that the idea you mentioned, about overriding asset tree, is actually the optimal one. The second would require designing API in code, and probably making all built-in text based (at least) components use it by default.

IMHO in theory it is possible to write simple text translation system similar to AGS on your own for your game, it's just that you would have to remember writing something like 'label.Text = Translation.Get("Original language text")' every time. Or maybe override/clone existing components and put that in them (not sure how easy that is).

cat

@tzachs: Thanks for the explanation, especially regarding .NET

I really like the AGS approach to translation. Just having to write the text in the base language and translation is done automatically is really convenient for the user. This could also be implemented without breaking the API, I suppose. Use a translation when available, otherwise just use the text.

tzachs

Right, sorry, I only talked about replacing the assets and forgot to talk about replacing the texts. I also like the approach of the text in the code written in the base language (I really dislike using some resource id without text so you don't know what's going on when you read the code). And I imagine having an interface in the text rendering pipeline which gets as input the base language string and returns a translated string, and the built in implementation will read the translation files and build a dictionary.
There's already an interface like this now specifically for speech that you can override and add translations in there, but nothing for HUDs yet, so I'll probably add that interface further down in the engine which will cover both scenarios (hope that makes sense). And of course there will be tooling on top, it'll combine both translations and speech into one GUI (both need to display all strings from the game) and will export translation/speech scripts etc. And to cap off the localization story there will be API to get the current language (and maybe also to set? Not sure how useful it would be to change the language at run-time) and change specific puzzles if needed based on the language (monkey wrench scenarios), and maybe also get some meta-data on the language (like is it right-to-left -> this is always a very painful thing to support in software, luckily I'm in a very good position for this).

cat

Quote from: tzachs on Sat 05/05/2018 21:23:54
Not sure how useful it would be to change the language at run-time
VERY useful. This allows for implementing language change buttons in the in-game menu. It think it's much more elegant to do it this way than having to run an external setup. Please also add a subscription handle for language changes to implement custom logic there.

tzachs

I wasn't thinking of an external setup but of a separate download altogether. Each voice pack is expensive in terms of hard-disk space, so my personal preference as a game developer will be not to force it on the player who knows which language she/he wants at download time anyway. But I realize other developers might have different preferences, and it is definitely useful for text only games.

Monsieur OUXX

#39
About the wiki page : I'm all in favor of a shared doc. CW has indeed noticed that I started writing tips in my very first post, buta shared document directly on the MonoAGS site is the best imo.

About the need of installing external packages : I wouldn't worry too much about that. We already had an extensive discussion (interrogation ;) ) with tzachs in another thread, and I'd say he has it rather well planned out -- provided he doesn't lose steam on the way to converting to .Net Core. In the future there should be a module testing that the requirements are present (maybe a pre-build script?), but for now it's not too tricky.

About the code that needs to be manually written and the absence of actual puzzles in the demo : maybe we should start a shared repository where we'd code some sort of basic middleware engine (a template, really) to make it easier to start a game with MonoAGS. Something that fills the current gaps until they're properly implemented by tzachs. Something as close as possible to an AGS game structre -- with comments in the code telling you where to insert code for this and that.
Maybe a NuGet package? So that the thingy can be recompiled by the maintainer(s) and then re-imported on the fly by all the people who use it?

EDIT : about that last point of starting to split optional game features into more readable and re-useable modules, I've got the perfect example : Demoquest is literally a Sierra template, which in turn uses the "Rotating Cursor" concept (right-click iterates through cursors). But that concept is also used by ... Sam&Max. We can clearly see how some game features could be enabled or disabled, and their generic code could be easily initialized from just a few parameters (in the case of cursors : the file containing the list of icon files of each cursor mode, and the text associated to each action).
So I'd suggest creating a separate library project in the solution with those features (the first of them being "rotating cursor", but I can give more examples : "scrolling inventory"). This library could then be included in each template (Sierra, 9-verb...).


EDIT 2 : On a different note: code-wise, how do you plan on binding an event function (such as : button.OnMouseClick(() => { .../* DO THINGS */ } ) ) from the in-game GUI? I have no trouble believing that the AGS Editor can simply insert some function name in game.agf and simultaneously insert an empty function with the same name in a game script file. It happens while the game is not running. But with Visual Studio, while the .exe is running, will that not be a bit tricky?

EDIT 3 : can you explain this piece of code
Spoiler

In Rooms.cs :
Code: ags

   EmptyStreet = Task.FromResult(Find(state, EmptyStreet.Result)); 


- I don't understand how EmptyStreet is populated after game gets loaded (in other words : how EmptyStreet is not null at the time "onSaveGameLoaded" gts called).
- I don't understand what is ".Result". Is it an "out" variable were find stores its result?
- More generally I don't understand the whole sequence.
    - Where does "Task" come from?
    - What's oldID versus ID? I'm guessing these are the IDs befaore/after load, but then again I fail to visualize the sequence of calls.
[close]
 

SMF spam blocked by CleanTalk