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 - tzachs

#181
Quote from: Crimson Wizard on Tue 22/05/2018 23:22:07
So in the end, it produced what seems to be a fine online documentation.
I uploaded it in separate folder for the time being:
http://www.adventuregamestudio.co.uk/manual/manual_3.4.1/

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

Edit: ah, nvm, it's now in http://www.adventuregamestudio.co.uk/manual/ if I understood correctly.
#182
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)!
#183
Quote from: cat on Tue 22/05/2018 17:19:59
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).
#184
Quote from: cat on Mon 21/05/2018 20:45:47
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).


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

Quote
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).

Quote
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: https://www.visualstudio.com/vs/support/community-edition-expired-buy-license/
#185
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).

Quote from: cat on Sun 20/05/2018 09:27:57
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.

Quote
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.

Quote
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?
Thanks.

Quote
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: csharp

var factory = game.Factory.Graphics;

var idle = await factory.LoadDirectionalAnimationFromFoldersAsync("Animations/Idle", "Left", "Down", "Right", "Up");

var walkLeft = await factory.LoadAnimationFromFolderAsync("Animations/Walk/Left");
var walkDown = await factory.LoadAnimationFromFolderAsync("Animations/Walk/Down");
var walk = new AGSDirectionalAnimation { Left = walkLeft, Down = walkDown };

var speakLeftImage1 = await factory.LoadImageAsync("Animations/Speak/Left/1.png");
var speakLeftImage2 = await factory.LoadImageAsync("Animations/Speak/Left/2.png");
var speakLeftSprite1 = factory.GetSprite();
var speakLeftSprite2 = factory.GetSprite();
speakLeftSprite1.Image = speakLeftImage1;
speakLeftSprite2.Image = speakLeftImage2;

//I'm missing a factory method to create an empty animation, so using the resolver for this (for now):
var speakLeft = AGSGame.Resolver.Container.Resolve<IAnimation>();
speakLeft.Frames.Add(new AGSAnimationFrame(speakLeftSprite1) { Delay = 3});
speakLeft.Frames.Add(new AGSAnimationFrame(speakLeftSprite2) { MinDelay = 4, MaxDelay = 8});
var speak = new AGSDirectionalAnimation { Left = speakLeft };

var jumpLeft = AGSGame.Resolver.Container.Resolve<IAnimation>();
float yOffset = 0f;
foreach (var idleFrame in idle.Left)
{
    var sprite = factory.GetSprite();
    sprite.Image = idleFrame.Sprite.Image;
    sprite.Y = yOffset;
    yOffset += 0.5f;
    var jumpFrame = new AGSAnimationFrame(sprite) { Delay = idleFrame.Delay };
    jumpLeft.Frames.Add(jumpFrame);
}
var jump = new AGSDirectionalAnimation { Left = jumpLeft };

var outfit = new AGSOutfit();
outfit[AGSOutfit.Idle] = idle;
outfit[AGSOutfit.Walk] = walk;
outfit[AGSOutfit.Speak] = speak;
outfit["Jump"] = jump;

#186
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.

Quote from: cat on Sat 19/05/2018 21:55:51
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: https://docs.microsoft.com/en-us/visualstudio/profiling/beginners-guide-to-performance-profiling
(If you share your project, I'll profile it).

Quote from: cat on Sat 19/05/2018 21:55:51
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?

Quote from: cat on Sat 19/05/2018 21:55:51
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.

Quote from: cat on Sat 19/05/2018 21:55:51
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.

Quote from: cat on Sat 19/05/2018 21:55:51
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.

Quote from: cat on Sat 19/05/2018 21:55:51
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.
#187
Quote from: Crimson Wizard on Sat 19/05/2018 15:17:59
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.
#188
Quote from: cat on Wed 16/05/2018 20:01:52
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.
#189
Quote from: cat on Tue 15/05/2018 20:12:05
I pulled the latest version but I get an exception when starting DemoQuest.Desktop at AGS.Engine.FileSystemResourcePack.autoDetectAssetsFolder line 104

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

I pushed a fix for this, can you pull again and retry?
Thanks.
#190
Cool, javascript has async/await too now, btw (they copied from c# and f#): https://javascript.info/async-await

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: ags

onRepeatedlyExecute()
{
    if (cGuard.X == 0 && cGuard.Y == 0 && !cGuard.IsMoving) cGuard.Walk(50, 0, eNoBlock);
    else if (cGuard.X == 50 && cGuard.Y == 0 && !cGuard.IsMoving) cGuard.Walk(50, 50, eNoBlock);
    else if (cGuard.X == 50 && cGuard.Y == 50 && !cGuard.IsMoving) cGuard.Walk(0, 50, eNoBlock);
    else if (!cGuard.IsMoving) cGuard.Walk(0, 0, eNoBlock);
}


In MonoAGS:

Code: csharp

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)
{
    while (true)
    {
        await cGuard.WalkAsync(50, 0);
        await cGuard.WalkAsync(50, 50);
        await cGuard.WalkAsync(0, 50);
        await cGuard.WalkAsync(0, 0);
    }
}


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.
#191
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: https://github.com/tzachshabtay/MonoAGS/blob/f7be8974648591740752d2c3be23ac2ea7990a4a/Source/Demo/DemoQuest/Program.cs#L23

to:

Code: csharp

string pathToMyAssetsFolder = "c:\cat\game\Assets";
game.Factory.Resources.ResourcePacks.Add(new ResourcePack(new FileSystemResourcePack(AGSGame.Device.FileSystem, AGSGame.Device.Assemblies.EntryAssembly, pathToMyAssetsFolder), 0));
#192
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.
#193
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).
#194
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.

Thoughts?
#195
Wow, that was fast, thanks! ;-D
#196
Editor Development / Re: AGS Build Server
Mon 14/05/2018 00:47:15
Both VSTS and Appveyor allow you to configure CI/CD on their hosted windows servers for free.
#197
Quote from: cat on Sun 13/05/2018 21:12:08
The splash screen (loadSplashScreen) has nothing to do with the Splash asset, right? It is the AGSSplashScreen from the engine but there does not seem to be documentation for it?
What do you mean by "splash asset"?
Yes, sorry, the splash screen is not currently documented, and is very basic for now. It's basically a blank room with a loading text that tweens its scaling until you tell it to move to another room.
You can change the text by setting the "LoadingText" property.
You can change the font/text color/outline/shadow/etc by setting the "TextConfig" property.
And when you call the load function on the splash screen you get back a reference to your room so you can set a background or add more stuff to the room (like any other room).
Here's an example which changes the text, changes it to a blue color and adds a background image:

Code: csharp

var mySplashScreen = new AGSSplashScreen();
mySplashScreen.LoadingText = "My Loading Text";
mySplashScreen.TextConfig = new AGSTextConfig(brush: game.Factory.Graphics.Brushes.LoadSolidBrush(Colors.Blue));
var room = mySplashScreen.Load(game);
room.Background = myBackgroundImage;
await game.State.ChangeRoomAsync(room);

...
//Load stuff here
...

await game.State.ChangeRoomAsync(firstGameRoom);


Quote
I am not sure how player character's position is synchronized with changing the room, haven't investigated that yet. Probably you may set Game.State.Player, but idk if it changes room automatically after the character.
If you change the player character's room it automatically changes the room in the game state as well, so the behavior matches what you expect when you change the player's position in AGS, but like CW said, you don't need to have a player character as you can just change the room in the state (which won't move the player character to that room). I think I set the player first because at the beginning I had the exact AGS behavior so the player was mandatory, but at some point I changed it.
#198
Quote from: Monsieur OUXX on Sun 13/05/2018 02:08:46
Based on these sources, does anyone understand why the word "Loading" does not appear?
Submitted a PR with a fix (you didn't change the current room to the loading screen).

Quote from: Crimson Wizard on Thu 10/05/2018 23:42:40
Quote from: Monsieur OUXX on Thu 10/05/2018 23:34:25
- is the root folder the execution folder?

Either location of exe, or "current working directory", and TBH that's kind of annoying. I believe there should be a way to configure this.

I had to invent a trick, because path may be different depending on whether you run the game from Visual Studio or from explorer.
What I do is that I pass a part of path as a command line argument when debugging the game, as "../../Assets/". And in game code I assign this argument to a variable called "_baseAssetFolder", which I use to construct resource paths.

By default _baseAssetFolder is just "Assets/", so that you could put Assets folder to same directory where exe is, and run it normally.

My best hopes are that in the end this is what resource loader's implementation will be doing on its own. So that we would have to type just "Images/room.png" instead of "../../Assets/Images/room.png".
I'm pushing a fix for this tomorrow (assuming the build goes well). This is a breaking change as the resources paths are now passed without the "../../Assets" prefix (i.e the default root folder will be the assets folder and it should work no matter where you run the game from). Please read the PR description for more details and let me know if you have questions/reservations.

Quote from: Monsieur OUXX

SWEET! ;-D
Permission to copy?
#199
To remove an entity from a room: room.Objects.Remove(myEntity);
Or if it's an area: room.Areas.Remove(myEntity);
To remove an entity from the GUI list: state.UI.Remove(myEntity);

After removing the entity from room/gui: myEntity.Dispose();
#200
Ah, ok, got you now. Yeah, I'm also not sure if we actually need this.
SMF spam blocked by CleanTalk