Porting game to MonoAGS

Started by cat, Sun 13/05/2018 21:12:08

Previous topic - Next topic

tzachs

Oh, that doesn't sound good. 
Can you send me your project? I'll investigate.

cat

Not sure if anyone else is following this thread, but I've sent my code to tzachs. He investigated the issue and found a temporary workaround.

A question on a completely different topic:
For the original AGS game I used a GUI to represent the border around the stage. It's basically a non-clickable GUI covering the whole screen and the center is transparent. What would be the best way to implement this in MonoAGS?

tzachs

It depends.

1. If you already have an image for the border which is the size of the entire screen, then you can do the same.
The equivalent of "A GUI" is a panel which you can get from the GUI factory (it's already "click-through" by default):

Code: csharp

factory.UI.GetPanel("MyPanel", myImage, x, y);


Note that unlike GUIs in AGS, if you want the panel to only be associated with a specific room and not all rooms, you can write it that like this:

Code: csharp

var panel = factory.UI.GetPanel("MyPanel", myImage, x, y, addToUI: false);
myRoom.Objects.Add(panel);


2. If you don't have a specific image you want for your border, you can use the "Border" property and set a built-in border (or you can code your own custom border rendering, but that's more involved and the API is not stable currently, the way it's done is very likely to change in the future).
Built in borders include a solid color border, a gradient border or a 9-slice image border (9-slice image border is similar to the 9 images you set on a border in AGS for message boxes, only a little more fancy, similar to a css border image: https://css-tricks.com/almanac/properties/b/border-image/).
So to create a transparent panel with a solid color border, for example, you can write:

Code: csharp

var panel = factory.UI.GetPanel("MyPanel", width, height, x, y);
panel.Tint = Colors.Transparent;
panel.Border = factory.Graphics.Borders.SolidColor(Colors.Blue, lineWidth: 3f, hasRoundCorners: true);



cat

Ah, in this case I will try a panel.

cat

#44
The panel frame is working :)

Is it possible to define a mask myself without a file? I just need a rectangle for the walkable area. If not, no worries, I'll just draw a mask.

Oh, and since you are the moderator in this board: Do you prefer that I edit posts with additional info or should I create a new post to bump the thread?


Edit: I just realized, I can probably do it with GetBitmap and then CreateMask?
Edit2: Seemed to work! I cannot walk yet, but PlaceOnWalkableArea() moves the character to where the WA is supposed to be :)

tzachs

Quote from: cat on Tue 18/09/2018 21:02:01
Edit: I just realized, I can probably do it with GetBitmap and then CreateMask?
Edit2: Seemed to work! I cannot walk yet, but PlaceOnWalkableArea() moves the character to where the WA is supposed to be :)
Cool! Very happy you figured it out without any specific documentation :)
Another way (just for posterity, what you did sounds better) would have been to create "new AGSMask" and give it a 2d boolean array.

Quote from: cat on Tue 18/09/2018 21:02:01
I cannot walk yet
Ah, so I think your game uses left to interact and right to look, right?
I have an incomplete implementation of that scheme in: https://github.com/tzachshabtay/MonoAGS/blob/master/Source/Engine/AGS.Engine/Input/Schemes/TwoButtonsInputScheme.cs
Not sure if what's there is in a working state or not (haven't touched it in a while but from brief examination of the code walking at least should work), you can try it by writing:
Code: csharp

var scheme = new TwoButtonsInputScheme(game, game.Input);
scheme.Start();

If it's working you should be able to walk.

If you're feeling up for it, it should be relatively simple to complete the implementation (just hadn't gotten around to it yet).
It's basically just looking at how it's done in the rotating cursors scheme (https://github.com/tzachshabtay/MonoAGS/blob/master/Source/Engine/AGS.Engine/Input/Schemes/RotatingCursorScheme.cs) without the actual rotating cursors stuff.
If not, then I'll get to it soon enough, hopefully in the next few days.

Quote from: cat on Tue 18/09/2018 21:02:01
Oh, and since you are the moderator in this board: Do you prefer that I edit posts with additional info or should I create a new post to bump the thread?
Bumping is fine. If you edit there's a chance I won't see it. Also I'm susbcribed to the topic so I'm getting an email whenever you post and can give you a quicker response.

Monsieur OUXX

Quote from: cat on Thu 13/09/2018 19:06:37
Why on earth can't they just provide a Windows installer?
Because linuxians. They like to capture the souls of innocent passerbys and torture them until they have entirely drained the will to live from them. They take a specific perverted pleasure in doing so by providing tools meant for Windows but made on Linux and yet not compiled for Windows.

What do you mean, "slightly biased comment"?
 

cat

Quote from: tzachs on Tue 18/09/2018 22:33:24
Cool! Very happy you figured it out without any specific documentation :)
Another way (just for posterity, what you did sounds better) would have been to create "new AGSMask" and give it a 2d boolean array.
I used Bitmap.SetPixels() with a list I built using nested loops. Is there a better way?

Quote
Code: csharp

var scheme = new TwoButtonsInputScheme(game, game.Input);
scheme.Start();

When I use this and click somewhere, nothing happens in the game but I see an exception in the output window:
Exception thrown: 'System.IndexOutOfRangeException' in AGS.Engine.dll

tzachs

Quote from: cat link=topic=56055.msg636595179#msg636595179
I used Bitmap.SetPixels() with a list I built using nested loops. Is there a better way?
Well, if you only want a rectangle, then just getting an empty bitmap should be enough, I think: factory.Graphics.GetBitmap(width,height)

Quote
When I use this and click somewhere, nothing happens in the game but I see an exception in the output window:
Exception thrown: 'System.IndexOutOfRangeException' in AGS.Engine.dll
Ok, I'll look into it.

cat

I want a rectangle that doesn't cover the whole screen, only a small part.

cat

In the meantime, I added the first object and to make things interesting, it's an object with animation. Good news first: it works :)
I'm just having trouble positioning the object. Using the original coordinates from the AGS game does not work. How is the position determined? Is there a proper way to calculate from AGS to MonoAGS coords?

Crimson Wizard

#51
Quote from: cat on Sat 22/09/2018 21:00:02
I'm just having trouble positioning the object. Using the original coordinates from the AGS game does not work. How is the position determined? Is there a proper way to calculate from AGS to MonoAGS coords?

Y axis is turned other way, pointing up :)
Also, in MonoAGS object's image related to Position is determined by Pivot (or was it Anchor? I may not remember correct property's name).
So, if your AGS object was located at X,Y your MonoAGS object should be located at X, Y = AgsRoomHeight - agsY, plus some extra offset depending on pivot/anchor.

I made this function to port AGS scripts:
https://github.com/ivan-mogilko/MonoAGSGames/blob/master/Games/LastAndFurious/Rooms/RoomScript.cs#L57

cat

Thanks, that did it! So it's the other way round. And I didn't know I had to reset the pivot first. What is the reason for having it 0.5, 0 initially?

tzachs

The pivot point is by default 0.5,0 for characters and 0,0 for objects. The reason it's 0.5,0 for characters is that it makes walk cycle animations align even when the front/back frames are in a different width from the side animations. Also I find it to be more intuitive when setting walk areas.

Also sorry that I haven't been more helpful lately, currently I'm on a 3 week vacation and a bit low on free time with proper internet..

cat

Quote from: tzachs on Sun 23/09/2018 11:04:12
The pivot point is by default 0.5,0 for characters and 0,0 for objects.
Sorry I have to correct you, but at least with version a4b22 the default pivot point for objects is 0.5, 0. I looked at it via debugger and when I reset the pivot to 0,0 the object is moved to the correct position.
I agree about the character pivot point and reasoning, though.

Quote
Also sorry that I haven't been more helpful lately, currently I'm on a 3 week vacation and a bit low on free time with proper internet..
No worries, enjoy your vacation! I see what I can do in the meantime by myself. Also a good way to see how self-explanatory the documentation is ;)

Crimson Wizard

#55
I think in the end it may be worth to not rely on engine's defaults and have a set of utility functions that init objects of different kinds. For example in the racing game I've referenced above I had function that setup a racing car object and it sets pivot to (0.5, 0.5), because it lets you to trivially apply rotation around sprite center.

This reminds me, when I last saw (several months ago) both alignment and rotation was performed around pivot, and there was a suggestion to split properties into one determining position alignment and another for object's own transform operations:
https://github.com/tzachshabtay/MonoAGS/issues/284


UPD.
Also, the Y axis pointing up makes it inconvenient to work with GUI, since you have to position, for example, menu items vertically in opposite direction (first item having largest Y). I wrote a class for the game menu that does calculations internally to simplify things for myself:
https://github.com/ivan-mogilko/MonoAGSGames/blob/master/Games/LastAndFurious/GameMenuComponent.cs#L169

I think I was asking if it's possible to implement a surface with custom axis direction, but don't remember what was tzach's decision on that.

cat

Thanks Crimson. I'll have another close look at your repostitory, since you have answers to many of my questions already :)

tzachs

Quote from: cat on Thu 20/09/2018 21:36:31
When I use this and click somewhere, nothing happens in the game but I see an exception in the output window:
Exception thrown: 'System.IndexOutOfRangeException' in AGS.Engine.dll
I can't reproduce this, so I need more information.
Is this the entire error message, no additional stack trace? Also, where did you put this code? And can you also write the code you used to add the walkable area? Or alternatively, can you send me your project again (with the error reproducing)?

Quote from: cat on Thu 20/09/2018 21:36:31
I used Bitmap.SetPixels() with a list I built using nested loops. Is there a better way?
...
I want a rectangle that doesn't cover the whole screen, only a small part.
Not necessarily better, but you can get an empty bitmap as I said before, and then add a translate component which gives you the ability to "move" an area on the screen.
It will look something like this, for example:
Code: csharp

var bitmap = factory.Graphics.GetBitmap(1000, 1000);
var mask = factory.Masks.Load("walkablemask1", bitmap, true);
var area = factory.Room.GetArea("walkablearea1", mask, _room, true);
area.AddComponent<ITranslateComponent>().X = 2000f;


Quote from: cat on Sun 23/09/2018 11:12:52
Sorry I have to correct you, but at least with version a4b22 the default pivot point for objects is 0.5, 0. I looked at it via debugger and when I reset the pivot to 0,0 the object is moved to the correct position.
I agree about the character pivot point and reasoning, though.
Ah, right, I think I changed it to all images after realizing the same logic applies, you can have multiple animations with different widths and it makes it easier to align by default (and also it's more consistent). I don't necessarily have too strong opinions on this, willing to discuss if you have a better suggestion.

Quote from: Crimson Wizard on Sun 23/09/2018 13:29:00
I think in the end it may be worth to not rely on engine's defaults and have a set of utility functions that init objects of different kinds. For example in the racing game I've referenced above I had function that setup a racing car object and it sets pivot to (0.5, 0.5), because it lets you to trivially apply rotation around sprite center.
This makes sense for a racing game, but I wouldn't want the average user to have to create utility functions for a point&click game. The engine should be geared with defaults that apply to the most common use-cases for point&click (or in the future, like we discussed, we might have templates with different defaults, geared to that specific template use case).
I think cat's struggle here stems for the fact that she's porting an existing game, I don't think she'd encounter this issue when creating a new game (we'll see when people actually create new games, though).

Quote from: Crimson Wizard on Sun 23/09/2018 13:29:00
Also, the Y axis pointing up makes it inconvenient to work with GUI, since you have to position, for example, menu items vertically in opposite direction (first item having largest Y). I wrote a class for the game menu that does calculations internally to simplify things for myself:
https://github.com/ivan-mogilko/MonoAGSGames/blob/master/Games/LastAndFurious/GameMenuComponent.cs#L169
Check out the built in Stack layout component which solves this problem (at least for laying out menu items). You add your buttons to a panel, then you add the layout component to the panel and it automatically lays them out for you (and you can set the spacing between the items).

Quote from: Crimson Wizard on Sun 23/09/2018 13:29:00
This reminds me, when I last saw (several months ago) both alignment and rotation was performed around pivot, and there was a suggestion to split properties into one determining position alignment and another for object's own transform operations:
https://github.com/tzachshabtay/MonoAGS/issues/284
Right, the jury is still out on this one. I'm keeping the issue open, but as I said, I'm not sure the added flexibility here is worth the added complexity.

Quote from: Crimson Wizard on Sun 23/09/2018 13:29:00
I think I was asking if it's possible to implement a surface with custom axis direction, but don't remember what was tzach's decision on that.
Same here, it can be done and it adds flexibility, but I'm again not sure the added flexibility is worth the added complexity.

Crimson Wizard

#58
Quote from: tzachs on Sun 23/09/2018 22:25:35
Quote from: Crimson Wizard on Sun 23/09/2018 13:29:00
I think in the end it may be worth to not rely on engine's defaults and have a set of utility functions that init objects of different kinds. For example in the racing game I've referenced above I had function that setup a racing car object and it sets pivot to (0.5, 0.5), because it lets you to trivially apply rotation around sprite center.
This makes sense for a racing game, but I wouldn't want the average user to have to create utility functions for a point&click game. The engine should be geared with defaults that apply to the most common use-cases for point&click (or in the future, like we discussed, we might have templates with different defaults, geared to that specific template use case).

You may find different use cases for the Origin (I will use this term, which is equivalent to Pivot at the moment) within same game or even within same room. For example:
Origin with Y = 0 will be convenient when setting up objects that need to be on "floor", because you want to align their feet/bottom to particular place there.
Origin in center (0.5, 0.5) is convenient for top-down views, but may be also useful if you are making small flying objects like projectiles, visual effects etc.
Origin with Y = 1 might be useful if you align things in top to bottom order on screen programmatically (e.g. GUIs). And also if you have something walking on the ceiling, I guess :).
I think in general that whenever you are aligning objects programmatically alot in your game you may want to make sure they have convenient origins for that.

Otherwise you'd had to do extra maths in all non-default situations. AGS does not have custom origin, so I had to do additional calculations to position car "characters" in my racing game, converting from physics coordinates into AGS character coordinates. In MonoAGS I simply set the pivot.

Crimson Wizard

Since I was referencing examples of my work I decided to update my games to the latest version of MonoAGS too. Some issues were easy to fix, but I am currently trying to figure out what happened to the IImageRenderer interface which I implemented as SpriteFontRenderer in my game.

SMF spam blocked by CleanTalk