adventuregamestudio / ags

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

Feature Request: Let camera position accept floats (somehow) #2427

Open ericoporto opened 3 weeks ago

ericoporto commented 3 weeks ago

Describe the problem Making the rellax module, it's hard to make the camera smooth is that the camera can only move in integer positions. Now that we have GUI scaling I have a workaround here: https://github.com/ericoporto/rellax/issues/7

Still, if there was some in AGS way to do this, it would be nice.

Suggested change I think internally we use floats in the engine for the transformations anyway, so we might as well give some way to the user to set the camera position as a float in some way. I don't have one suggested change, but I have a few alternatives (there may be more).

Well, there may be other ideas. Other approach could be AGS have it's own smooth camera internally that could be turned on and it would just be smooth - I think this is less flexible though.

A more convoluted approach would be the API takes float but there are two new instructions in the interpreter to convert between integer and float (and float to integer) with some pre-defined rule and the compiler would be changed to automatically cast between these two primary types. I don't like this much, feels like a lot of work, it's a tradeoff between things working out without too much effort but also failing mysteriously because you used the wrong type.

The problem here is not implementation, it's design.

ivan-mogilko commented 3 weeks ago

have a different position api that uses float and keep the previous position as integer

This seems like an easy way to go. Removing an integer properties will not simply break scripts, but may cause inconvenience for people since AGS cannot cast types without function IntToFloat and FloatToInt.

Having extra pair of properties in floats would allow to have both. Names like Xf, fX, XF... something like that. In such case integer X and Y would return a rounded value.

But then, should not Size also be in floats?....

ericoporto commented 3 weeks ago

The advantage for size being float would be smooth zoom, but I haven't played much with that to have an opinion.

I think the viewport stuff being integers is fine because they map directly to the screen which is always in pixels which are integers - like, even if we had dynamic game screen sizes.

The only "issue" of the camera being float is the benefit depends on the user coding their own camera but I don't think it's that hard. I imagine most of the benefit would still rely on the users using some module that would use this new API.

Ah the float issue is also mostly for low resolution games, I don't think the camera moving in integers is that noticeable in higher resolutions.

ericoporto commented 3 weeks ago

Attempt a quick test with a terrible code just to see what happens (https://github.com/ericoporto/ags/commit/b96db04d7d457805b85958d21d7291a30a3d1332), project is CamFloatTest.zip. The AGS script code of this is just

float lerp(float from, float to, float t)
{
  return (from + (to - from) * t);
}

void late_repeatedly_execute_always()
{
  Game.Camera.X = lerp( Game.Camera.X, IntToFloat(player.x)-160.0, 0.025);
  Game.Camera.Y = lerp( Game.Camera.Y, IntToFloat(player.y)-120.0, 0.025);
}

while this surprisingly ridiculous code already produces some smoothing now that the camera position uses float the actual rendering will still clamp the pixels of the camera, so it seems internally there are more things that would have to change to enable this than I thought at first.

Uhm, curious, would this only work with render sprites at screen resolution or would there be a way to render the camera insides normally but only move the pixels relatively to the camera?

ivan-mogilko commented 2 weeks ago

There are alot of ints in renderSprite code, and perhaps spritebatches also have some ints in their settings.

I probably will be able to look later today. I suppose it's not necessary to change sprite positions to float, but it's important that sprite batch's translation (x,y offset) is not restored to int at any point. It may be better to start from the final stage of texture rendering (RenderSprite method) and go "up" from there.