Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.

Messages - tzachs

Pages: [1] 2 3 ... 57
You can try the answer here if you haven't already (it has 2 way conversions- days_from_civil and civil_from_days):

EDIT: Oh, and about this:

Another solution vga256 and me tried was to use Julian/Gregorian conversions and that seemed to be quite a good solution but unfortunately AGS doesn't really work well with float :(
I seriously doubt AGS doesn't "work well with floats", but rather floats as a data format have limitations which means you can't do accurate calculations with them. It's not AGS specific, all languages suffer from that, see here:
This is why some languages offer another data type which can do more accurate calculations, like decimals in c#, at the expense of performance.

Well, the hacky solution (without understanding the code, just based on the behavior you're describing) would be to move the "reduce one year" line to the end of the function, just before the return.

Note, though, that dealing with time is incredibly complex with like a billion of edge cases, so no matter what, test a lot.
Some reading material to appreciate the complexity:

For example, during character creation, I assign an outfit only for left:
IOutfit outfit = await game.Factory.Outfit.LoadOutfitFromFolde rsAsync(_baseFolder, walkLeftFolder: "Walk", speakLeftFolder: "Walk", idleLeftFolder: "Walk");
and then I start the idle animation for down (because I didn't pay attention):
The problem is, the game gets stuck on the loading screen and the exception is only visible in output.
This should be fixed now (the game will properly crash with an error message).

Also, I saw that there's a bug with how the fade transition works in your loading screen (instead of fading in the new room, it's fading in the splash screen). Not yet sure what's going on there, it seems more complicated, I will look at it after I finish my current work.
This should also be fixed now.

Engine Development / Re: AGS engine Mac OS X port
« on: 05 Jun 2018, 18:16 »
Ah, right, forgot about the SDL effort, yeah, they seem to have vulkan support for mac:

Engine Development / Re: AGS engine Mac OS X port
« on: 05 Jun 2018, 16:12 »
Heads up: Apple is deprecating OpenGL for macos: :~(

Seems as the 2 possible options for supporting mac long term are either metal or vulcan using moltenvk (and of course supporting vulkan should give performance benefits on all platforms whereas metal is apple platforms only).

Site & Forum Reports / Re: Updating online manual
« on: 31 May 2018, 17:06 »
So in the end, it produced what seems to be a fine online documentation.
I uploaded it in separate folder for the time being:

This link seems to be broken now (I'm getting a 404).

Edit: ah, nvm, it's now in if I understood correctly.

General Discussion / Re: Frustration/ranting/market
« on: 25 May 2018, 15:01 »
Adding to what has already been said (identify your target audience and have a clearer trailer), what you are really missing is unique selling points (USPs). What does your product offer that the competition doesn't?
For that, of course, you need to find the competition first. A quick google showed Mega Scatter for unity, but I'm sure there are more.
So you should look at the competition and decide: is there a feature that I offer and they don't? Is using my product will make the user more productive? or if your product is inferior, you can also offer a cheaper price which can be your USP.
Whatever your USP is (or are), it should be emphasized in the trailer.
And the trailer's call to action (the link in the end) is barely visible, it needs a little more screen time and a bit more nudging (like "to learn more: link"). And the link itself (to the facebook page) doesn't seem to work (I'm getting "the page isn't available") -> make sure the link is actually working.

So once you have a legit trailer, and a legit working link with more info/tutorials/etc, and you know who your target audience is, you need to go where the target audience is.
So if your audience is game developers, go to unity/unreal/godot/etc forums. And if your audience is 3d artists go to maya/3dmax/blender forums. And of course if you do offer plugins to those products that's a great advantage (and if you find a popular product which doesn't have a plugin -> this might be a good place to create a plugin for, as you'll be filling a hole).

Good luck (your product seem nice)!

Ah, I thought it might be something like that :-\ Well, can't complain too much about a free product. I assume when the MonoAGS editor is finished, people will not need VS installed, right?
Technically, you don't need VS even now. Any IDE/text editor which can compile c# code can be used (in theory, at least).
Once the first version of the MonoAGS editor will be released, you should be able to use any text editor even if it can't compile c# yourself as the editor will be able to compile the code. However, you'll probably still want to use an IDE for debugging purposes.
Then I'll look into the option of bundling the editor with an existing IDE (we previously talked about either MonoDevelop or VS Code as potential candidates), and also of having the editor as an add-in to VS itself (so 3 flavors: standalone, standalone bundled with text editor and debugger, add-in to VS -> hoping it wouldn't be too big a burden, otherwise we'll need to make a choice and cut).

I understand that, but the whole interface composition will be too complicated for the regular game developer. The documentation needs to have an article where everything you can do with a character is explained in the style of the old AGS doc.
The character page has everything you can do with the character in link format, so it's similar to the AGS doc except for the link itself does not to point to the same page. I'm not sure there's an easy way to copy the link contents to the character page, I'll need to get a deeper understanding of how the documentation is auto generated. Hopefully I'll get to that at some point.
I reported the new scenario for the broken search, and they're investigating it, so hopefully it will improve the situation (and interestingly if you search for "*ChangeRoomAsync*" it does work).
Also note that I plan to have the documentation for the interactions available from within the (yet to be written) interaction editor (so each interaction will have a "?" button next to it or something like that).

Thanks! It would be great to have a shortcut, like factory.LoadSpriteFromFile or similar.
Done ("LoadSprite" and "LoadSpriteAsync").

Can I safely reuse a sprite for different frames or should I create/clone a new one?
It depends. If you share the sprite it means you also share the sprite's configuration (rotation, scaling, translation offset, pivot, tinting, brightness). In other words, if you use the same sprite on 2 animation frames, and you rotate the sprite in one of the frames it will also rotate it for the other animation frame. If that's what you want, or, if you don't intend to change configurations for individual sprites (and if you intend to port the game from AGS as is without changes, then you don't) you can safely share the sprites. But if you want independent configurations, then use different sprites (but they can still share the same image, which is safe).

One more (not exactly MonoAGS) issue I have: I installed the VS Community Edition, which I thought was free? But now VS says that my 30 days trial license will expire in a few days ???
It is free, but you need to sign in, see here:

I pushed fixes to master for both the camera panning issue and the character speaking.
Note that I removed Character.Say, SayAsync should be used instead, that's because the blocking say can't work in all scenarios (like in after fade in, because it's blocking it also blocks the completion of the event so you will not see it happening). If I return it (technically it's not needed, SayAsync can do everything Say can do) I'll need to think of a more sophisticated way for it.

Also, I saw that there's a bug with how the fade transition works in your loading screen (instead of fading in the new room, it's fading in the splash screen). Not yet sure what's going on there, it seems more complicated, I will look at it after I finish my current work.
For the mean time, if it bothers you as it bothers me, you can remove the fade transition from the game load event, and move it to after your first (non splash screen) room fades in. Note that this will also reduce the time of the splash screen (by default the fade transition is 1 second fade in and 1 second fade out).

I know it would be easier to make a public github repo for it, I'm just not sure I really want to make it all public (not because of the code but the general copyright to the game and assets).
You can also create a private repository. It costs money on github, but it's free on both VSTS and BitBucket.

Btw, when searching for ChangeRoomAsync* only IHasRoomComponent is in the result, not ICharacter.
This is because ICharacter doesn't really contain ChangeRoomAsync, it's composed out of components (like IHasRoomComponent) which contain the actual behaviors.

Right, I checked again and I see a null reference exception in output. However, the program doesn't crash but nothing else happens and the game is stuck.
Can you describe what changes I need to make to reproduce this? Also, if possible can you share the stacktrace of the null reference exception?

Btw, is there another way of setting the character outfit? I want to reuse some frames for an animation and not copy them several times in resources. I'd like to build the animation manually.
Yes, you can.
An outfit is a collection of directional animations (idle/walk/etc), a directional animation is a collection of animations (left/right/etc), an animation is a collection of animation frames, each animation frame is sprite + more configurations for the frame (sound and delays), and a sprite is an image + more configurations for the sprite (rotation, scale).
So you can pick and choose at what level you want to share your resources, which dictates which factory method(s) to use: the graphics factory has methods to load directional animations, to load animations, to load images, and also to get empty sprites.

So here's an untested example that combines some of those together to create an outfit.
We'll load the idle directional animation directly from folders, we'll create the walking directional animation by loading a few animation folders ourselves and create the directional animation from it, we'll create the speaking directional animations by loading images, creating animations from them and add to a directional animation, and finally, we'll create a jump directional animation by taking the images from the idle directional animations and just shift their offsets a bit to do a (really silly) "programmatic" jump.

Code: C#
  1. var factory = game.Factory.Graphics;
  3. var idle = await factory.LoadDirectionalAnimationFromFoldersAsync("Animations/Idle", "Left", "Down", "Right", "Up");
  5. var walkLeft = await factory.LoadAnimationFromFolderAsync("Animations/Walk/Left");
  6. var walkDown = await factory.LoadAnimationFromFolderAsync("Animations/Walk/Down");
  7. var walk = new AGSDirectionalAnimation { Left = walkLeft, Down = walkDown };
  9. var speakLeftImage1 = await factory.LoadImageAsync("Animations/Speak/Left/1.png");
  10. var speakLeftImage2 = await factory.LoadImageAsync("Animations/Speak/Left/2.png");
  11. var speakLeftSprite1 = factory.GetSprite();
  12. var speakLeftSprite2 = factory.GetSprite();
  13. speakLeftSprite1.Image = speakLeftImage1;
  14. speakLeftSprite2.Image = speakLeftImage2;
  16. //I'm missing a factory method to create an empty animation, so using the resolver for this (for now):
  17. var speakLeft = AGSGame.Resolver.Container.Resolve<IAnimation>();
  18. speakLeft.Frames.Add(new AGSAnimationFrame(speakLeftSprite1) { Delay = 3});
  19. speakLeft.Frames.Add(new AGSAnimationFrame(speakLeftSprite2) { MinDelay = 4, MaxDelay = 8});
  20. var speak = new AGSDirectionalAnimation { Left = speakLeft };
  22. var jumpLeft = AGSGame.Resolver.Container.Resolve<IAnimation>();
  23. float yOffset = 0f;
  24. foreach (var idleFrame in idle.Left)
  25. {
  26.     var sprite = factory.GetSprite();
  27.     sprite.Image = idleFrame.Sprite.Image;
  28.     sprite.Y = yOffset;
  29.     yOffset += 0.5f;
  30.     var jumpFrame = new AGSAnimationFrame(sprite) { Delay = idleFrame.Delay };
  31.     jumpLeft.Frames.Add(jumpFrame);
  32. }
  33. var jump = new AGSDirectionalAnimation { Left = jumpLeft };
  35. var outfit = new AGSOutfit();
  36. outfit[AGSOutfit.Idle] = idle;
  37. outfit[AGSOutfit.Walk] = walk;
  38. outfit[AGSOutfit.Speak] = speak;
  39. outfit["Jump"] = jump;

Would it be possible for you to share a copy of your project with me?
Without it it's going to be much harder to help.

It's just one background, no objects, music and stuff - yet, the loading screen is shown for a full second or so. Why does it take so long? Is it because of the big background?
I don't know. How big is the background (file size)?
You can try commenting out the line that loads the background and comparing the time differences.
Also, if you feel up to the challenge, you can profile the loading time to see what's taking up time. There's a built in profiler when you debug in visual studio:
(If you share your project, I'll profile it).

When the background is shown, after fade in, it quickly pans to the location which is undesired. Is this done automatically? I think it should fade directly to the position where I call change room. Or is it something different here?
It should fade directly to the position when you change room. Are you changing the viewport positions manually? Or are you moving the character in "after fade in"? Because if you move the character after the room fades in then the camera will not change at once but will do a smooth movement so maybe that's what happenning?

I couldn't find documentation for Character.ChangeRoomAsync, especially how the coordinates work (i.e. where is 0,0)
Yes, I need to add a doc page on all the co-ordinates systems in the engine.
(0,0) is the bottom left.
Docs for Character.ChangeRoomAsync is here (though there's not much there).
And you can access it directly from the ICharacter page.
A tip if you tried using the search: there's currently a bug in DocFX that the search misses things. You can work around it by searching for "ChangeRoomAsync*" instead of "ChangeRoomAsync".
Here's a link to the bug. If you (or anybody) wants to comment on it and maybe put some more pressure on them to fix it already it would be nice.

It's hard to find/understand errors that occur. When resources for the walkcycle were not there, loading wouldn't work and I was stuck on splash screen, I only found the cause of the error when stepping through initialization with the debugger.
If you're running in "Debug" from visual studio there's printouts to the output tab. Did you look there for errors?
Otherwise, not sure, I'll need to reproduce and see what went on there.

My character is not visible yet. Do I have to do something special to show it? I changed the room and the screen is on the correct position.
Besides having the character in the same room, you also need to start the idle animation (or any animation, or set an image). You just need to do it the first time, it will then transition back to idle automatically after walk animations.

I tried to say something after the room change, but the game crashes on me:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.' at AGS.Engine.OpenGLBackend line 30.
Can you share the complete stacktrace of the exception?
Also, can you try changing from "Characters.Cornelius.Say("Hello, here I am.");" to "await Characters.Cornelius.SayAsync("Hello, here I am.");" and see if it helps?
If it doesn't help, you can also try doing the say (or say async) in the "after fade in" event of the "stage" room instead of the splash screen room and see if that works.

In the past there was a suggestion to introduce new type, something like "AudioPlayback", which is returned from AudioClip.Play instead of the channel. By assumption, that would reduce the problems people have when storing AudioChannel pointer for a long time, which may later get other clip played on it. Is it a good idea?

This is what MonoAGS is doing (only the result is called "Sound" and not "AudioPlayback"), and yes, I think it's a good idea. MonoAGS has no concept of "channel" at all which I think makes things simpler with less confusion.
The only use-cases I see for channels are:
1. Having a "radio" in your game: you can still simulate channels if you need it.
2. Exhausting all the hardware channels: less of a problem on newer devices, but you can still resolve it by allowing setting priorities for sounds without needing to introduce channels.

Edit: And another question about LoadOutfitFromFolders:
I see in the demo game that only speakLeftFolder for talk and walkLeftFolder and walkDownFolder for walk are used. How does the engine decide which one to use for what, e.g do I always have to provide speakLeftFolder when I want to have the same animation for all talk animations or could I also use speakRightFolder? This is missing in the code comments/documentation (or did I just not find it?)

Yes, you can use speakRightFolder instead of speakLeftFolder (in general, the engine will try to use the closest directional animation it has). Documentation mentions it here.

And predicting a potential next question, yes, it currently does support only 8 directions, should add support to 360 (or rather, infinite because it will probably be a float) possible directions at some point (and we'll still have shortcuts to the 8 directions -> up will point to 0, down to 180, etc) and we'll probably also want explicit support for top-down views which will just rotate the sprite.

I pulled the latest version but I get an exception when starting DemoQuest.Desktop at AGS.Engine.FileSystemResourcePack.autoD etectAssetsFolder line 104

System.ArgumentException: 'URI formats are not supported.'

I pushed a fix for this, can you pull again and retry?

Cool, javascript has async/await too now, btw (they copied from c# and f#):

Anyway, in case it's helpful, here's a really quick primer for AGSers on async/await:

AGS:     cEgo.Walk(eNoBlock)
MonoAGS: cEgo.WalkAsync()

AGS:     cEgo.Walk(eBlock)
MonoAGS: await cEgo.WalkAsync()

AGS:     cEgo.Walk(eNoBlock); /* Do stuff */ while (cEgo.IsMoving) Sleep(1);
MonoAGS: var walkTask = cEgo.WalkAsync(); /* Do stuff */ await walkTask;

This 3rd scenario is where async/await starts to add value. For walk you can check IsMoving on AGS, but for "say background" you'll need IsSpeaking, and you'll need more APIs for each async (non blocking) operation, whereas the API is always going to be the same with async/await. And it's not even going to be perfectly accurate in the AGS way of doing things, as while you were sleeping it might be possible (in case you have multiple threads) for the character to walk again because another command told the character to walk so you'll keep waiting. With the async/await scenario you know you're waiting for YOUR walk command, so you can't have this problem.

And where it really starts to shine is when you chain multiple async/await in whatever way you want.
For example, imagine a guard walking in the background between 4 different points in an endless loop.
In AGS, I would write something like this:

Code: Adventure Game Studio
  1. onRepeatedlyExecute()
  2. {
  3.     if (cGuard.X == 0 && cGuard.Y == 0 && !cGuard.IsMoving) cGuard.Walk(50, 0, eNoBlock);
  4.     else if (cGuard.X == 50 && cGuard.Y == 0 && !cGuard.IsMoving) cGuard.Walk(50, 50, eNoBlock);
  5.     else if (cGuard.X == 50 && cGuard.Y == 50 && !cGuard.IsMoving) cGuard.Walk(0, 50, eNoBlock);
  6.     else if (!cGuard.IsMoving) cGuard.Walk(0, 0, eNoBlock);
  7. }

In MonoAGS:

Code: C#
  1. async void guardWalkLoop() //Using "async void" to let people know I'm a "fire and forget" method. If I want whoever calls me to wait for me to finish, I'd change the signature to "async Task" (but then I can have a "while true" in the method)
  2. {
  3.     while (true)
  4.     {
  5.         await cGuard.WalkAsync(50, 0);
  6.         await cGuard.WalkAsync(50, 50);
  7.         await cGuard.WalkAsync(0, 50);
  8.         await cGuard.WalkAsync(0, 0);
  9.     }
  10. }

Now imagine you want the guard to say something between a few of the points, or if you want to change routes, of have multiple guards walking in parallel but occasionally need to sync with each other, it gets really hard in AGS and is trivial with async/await.

I have a fix for this which I'll hopefully push tonight.
Meanwhile you can work around it by passing the path to your assets folder to the constructor of FileSystemResourcePack which bypasses the auto detection code.

I.e change the line here:


Code: C#
  1. string pathToMyAssetsFolder = "c:\cat\game\Assets";
  2. game.Factory.Resources.ResourcePacks.Add(new ResourcePack(new FileSystemResourcePack(AGSGame.Device.FileSystem, AGSGame.Device.Assemblies.EntryAssembly, pathToMyAssetsFolder), 0));

Added a doc for the splash screen and added the splash background asset to the splash screen in the demo game so it's being used now.

I think speed is still relevant, if SkiaSharp loads images from file faster, it means less waiting time until your game starts, or when switching rooms, etc (though I'm not sure how big is the performance difference on practice). And yeah, svg support is something I really want to have (there is some hope that ImageSharp would be able to work with svg in the future but it's not a guarantee).
As for ease of use, ImageSharp is the winner, though (and they are tied regarding expected lifetime and support, they are both in very active development and popular).

I wanted to share a dilemma I'm having and maybe get some feedback. It's about which library to choose for loading/manipulating bitmaps, vector drawing on bitmaps and text rendering.
Currently we're using GDI+ on desktop and native APIs on mobile.
Reasons I want to move:
1. Be able to share code between desktop and mobile.
2. GDI+ has been a little buggy in the past, and it's single threaded only.
3. The real deal breaker, though, is loading custom fonts (i.e fonts that are not installed on the system). It seems to be completely broken. It used to work on Windows but not work on Mac and Linux, but now it stopped working on Windows too, and I have no idea why. On Linux & Mac I can do an ugly workaround by installing the fonts and restarting the game, but on Windows I can't even do that unless the application runs with elevated permissions, and I don't want to force people running the game as administrator. And it becomes urgent to move now, as I want to use font awesome for icons in the editor and I don't want to force people to install the font.

Both ImageSharp and SkiaSharp claim to be fully cross-platform and appear to support loading custom fonts and be able to run concurrently, so all of those should be solved (well, we'll need to test).
ImageSharp is a fully managed solution and community based, while SkiaSharp is a managed wrapper around Skia -> Skia is used by Google Chrome and developed by Google and SkiaSharp is sponsored by Microsoft.

Differences between the 2 libraries:
1. ImageSharp being a fully managed solution will be easier to debug if something goes wrong, probably be more portable because one less dependency (although skia is also probably very portable if used by chrome) and easier to deploy, and easier for us to contribute to if we need to make changes (and is more popular among developers, maybe for that reason).
2. SkiaSharp is faster than ImageSharp, and it allows in theory to have hardware-accelerated text rendering (in practice, I haven't actually managed to get it to work, and even if I did, as we want to also attempt moving to Veldrid we won't be OpenGL only anymore so we might not be able to use this feature anyway), and it also supports SVG rendering via an extension which ImageSharp does not currently support.


Site & Forum Reports / Re: New sub-forum for MonoAGS
« on: 14 May 2018, 00:49 »
Wow, that was fast, thanks! ;-D

Pages: [1] 2 3 ... 57