adventuregamestudio / ags

AGS editor and engine source code
Other
707 stars 159 forks source link

AGS 4: support creating and loading sprites in a non-default color depth #2455

Closed ivan-mogilko closed 4 months ago

ivan-mogilko commented 5 months ago

Resolves #2027

This implements an ability to create and load sprites in a different color depth than the game's default color depth. This is not meant for a common use, but special cases, such as having 8-bit masks as sprites in 32-bit games. Therefore I tried to not overdo with options here and keep new parameters to a reasonable minimum.

Introduced ColorFormat enum:

enum ColorFormat
{
  /// Tells to use default game color depth
  eColorFmt_Default = 0,
  eColorFmt_8bit    = 8
};

Added ColorFormat color_fmt parameter with eColorFmt_Default default value to the following functions:

This "color_fmt" parameter tells engine of which depth to create this sprite. Value 0 means "use game default". Another supported value that engine currently supports is eColorFmt_8bit (meaning 8-bit indexed bitmap). In theory we could also support 1-bit and 4-bit masks later.

In #2027 we discussed potentially having a "pixel format" enum instead, which lets more fine tuning here. As I mentioned in the conversation there, I had change of opinion regarding that. Such thing may be useful internally inside the engine, but IMO has a very little meaning in script, and will only confuse majority of the users. For 99% use cases it will be enough to have a either a default color depth, or a specific color depth which is cast to default pixel format corresponding to that depth by the engine.

If we'll have a reason for defining a precise pixel format, I think that existing "ColorFormat" may be expanded with:

Finally, couple more properties are added which let to read color depth:

int DrawingSurface.ColorDepth;
int Game.SpriteColorDepth[];
ivan-mogilko commented 5 months ago

Hmm, perhaps I found another argument for having enum for color format: it is to have a clear list of which values are officially supported.

I'll think about it...

ericoporto commented 5 months ago

Perhaps it only has to be two formats: game color format and mask color format, and then if it's mask color format it would be possible to use the pathfinder API in this sprite. (Also is it missing enabling Mask Pathfinder here?)

I don't like much the idea of exposing the color depth as an int for something that user has to input, and I think it would be only two values: 32 and 8.

ivan-mogilko commented 5 months ago

Perhaps it only has to be two formats: game color format and mask color format

Possibly... except there may be a use for multiple mask formats (starting with 1-bit).

For the starters the enum could be

Also is it missing enabling Mask Pathfinder here

Right, I tested MaskPathfinder, fixed couple of bugs (in the main repo), and rebased with MaskPathfinder re-enabled. In my simple test, at least, it works with a loaded 8-bit sprite, lets to find paths etc.

The only strangeness I found is that GetPixel returns -1 (COLOR_TRANSPARENT) for 8-bit pixels with 0 value, which is inconvenient when you scan the mask yourself. This is the historical behavior of AGS.

ivan-mogilko commented 5 months ago

I will have to make a break in my work for several days, but I will try to re-think these options in the meantime.

ivan-mogilko commented 5 months ago

New simpler variant.

Introduced ColorFormat enum:

enum ColorFormat
{
  /// Tells to use default game color depth
  eColorFmt_Default = 0,
  eColorFmt_8bit    = 8
};

Added ColorFormat color_fmt parameter with eColorFmt_Default default value to the following functions:


The next addition afterwards is supposed to be a similar selection in "Import sprite" window.

ericoporto commented 4 months ago

MaskPathFinder.zip

This appears to work. I decided to play with MaskPathFinder, it seems it works exactly as I thought it would using 0 for the transparent 8 bit color and any other color to make it a walkable area, and it also blends with the mask colors when just randomly merging an 8-bit dynamic sprite in a non-8-bit one, which also makes things easier! Two things appeared, but they are in pathfinder and not in the dynamic color.

ivan-mogilko commented 4 months ago

Passing a null where a path is accepted moves things to position (0, 0), I believe it should just not do anything and print a warning on log.

Fixed this one in ags4 branch, it was a mistake in MovePath/WalkPath functions.

After clicking and walking a lot with the character at the borders it is possible to click to somewhere where there is a path and get no path after a while.

This must be a mistake in the JPS pathfinder. When testing new functions, displaying both mask and path on screen, I also noticed that it "cuts corners" sometimes. Easy to see if you make a mask with strict rectangular walls.

it also blends with the mask colors when just randomly merging an 8-bit dynamic sprite in a non-8-bit one, which also makes things easier

To clarify, there's currently a mistake that ags4 has blitting broken between 8-bit and 32-bit sprites, because alpha channel is not filled with opaqueness, instead it is left as 0, which makes all non-0 colors blit as fully transparent. The correct behavior should be to have 8-bit colors converted to 32-bit using palette with full alpha. This must be fixed, but separately.