GDevelopApp / GDevelop-extensions

Repository of behaviors, actions, conditions and expressions to be used in GDevelop for creating games
https://gdevelop.io
MIT License
131 stars 53 forks source link

Change camera zoom with mouse wheel or keys #200

Closed Elairyx7301 closed 2 years ago

Elairyx7301 commented 3 years ago

 

This rest of the original description and the files are outdated.

The final and merged version is v3.0.6. See the files for it here.

Files v3.0.6

Project.zip CameraZoom.zip

     

     

Quick overview

Change the zoom scale of a camera with the mouse wheel / keyboard keys, contains camera zoom as a regular action and one for limiting camera zoom scale.

Describe the extension

With this extension, the user can change the zoom scale of any camera on any layer using the mouse wheel or custom keyboard keys and the step of zooming can also be changed. The extension does not feature expressions or conditions since it's only manipulating the regular camera zoom and there already is a list of expressions and conditions for the current camera state including its zoom scale.

In combination with the "Drag camera with pointer" extension, this can make for a sweet RPG map layout, a searching game of any kind, a platformer where you have to move the camera manually while being under pressure (that's a fun idea, by the way ;) and anything the like.

Important parameters like "zoom step", "camera" and "layer" are dynamic and hence can be changed with the expression builder as well.

Extension Actions (v1.0.6)

Checklist

List of all actions (v1.0.6)

actions

Image of events used in the game file (v1.0.6)

events

Example video (v1.0.5)

This is a video showing the extension. The video was made with the extension project example linked below.

https://user-images.githubusercontent.com/83909121/133308174-5251d61f-31b3-4fb1-a87a-7ea472502314.mp4

Extension file (v1.0.6)

outdated

Elairyx7301 commented 2 years ago

I just tested the sprite scale and it seems to be absolute for me. image Holding down the key with this event will only scale the player to 1.2 and not increase the scale every frame.

I don't know if we're talking about the same "relative" anymore 😅

Elairyx7301 commented 2 years ago

2.0.1

Done

- Changed rel. zoom range from [-1; 1] to [0; +∞] - Adjusted label and description of parameter - Fixed typos - Polished project settings

Not done, why?

Not implemented TimeDelta()

I still have no idea how I am supposed to use TimeDelta(). I know it should be included in the equation to compensate for different fps. I am very sorry about still not being able to get it, I have tried several times, I've did experimentation with a graph visualizer, I've calculated it through in my head with various examples and I have not gotten to a result I could be happy with. Concerning the formula, I doubt we'll be needing an exponential or "power of n" expression here, since the relation between fps and speed or rather target, if I'm not completely mistaken, is linear.

Not replaced parameters ZoomChange and ZoomTarget with parameter ZoomFactor

I don't see the two parameters as too complicated to understand. I am convinced that the current method even lets the user handle the actions more easily because of the two separate parameters. Example: When toggling between zoom level 1 and zoom level 0.5, the user can freely and dynamically change the speed with a variable (for a "slow motion" effect or instant zoom, etc.) without having to recalculate the speed the camera should zoom per second for the same result. Additionally, the TimeDelta() issue was preventing me from making this change due to the "1 second" specification and definition.

This change should not be a problem to get done at all and I will happily do so if I get outvoted but I just want to say that this would not be my preferred option due to already mentioned reasons.

Files

Extension.zip v2.0.1.zip

I wish you all a very, very merry Christmas 🎄😄

D8H commented 2 years ago

Exponential

Concerning the formula, I doubt we'll be needing an exponential or "power of n" expression here, since the relation between fps and speed or rather target, if I'm not completely mistaken, is linear.

A "constant" zoom is exponential. A zoom out by 0.5/second with TimeDelta=1s is like this: 1, 0.5, 0.25, 0.125... and not: 1, 0.5, 0, -0.5. If you draw it, you will see it looks like an exponential because it is one.

Parameters

Not replaced parameters ZoomChange and ZoomTarget with parameter ZoomFactor I don't see the two parameters as too complicated to understand. I am convinced that the current method even lets the user handle the actions more easily because of the two separate parameters. Example: When toggling between zoom level 1 and zoom level 0.5, the user can freely and dynamically change the speed with a variable (for a "slow motion" effect or instant zoom, etc.) without having to recalculate the speed the camera should zoom per second for the same result. Additionally, the TimeDelta() issue was preventing me from making this change due to the "1 second" specification and definition.

When I was talking about using different parameters, it was about the "relative" zoom.

For the "absolute" zoom, it's an interesting idea to let users ease the zoom with a parameter, but I think It will be easier to try to have a working constant zoom 1st and add this feature then. I don't really understand what you want to do with the "absolute" because if it should reach a target, it should be a one time action that execute in a life-cycle function. But, this will be exactly the same as a zoom tween that should be done by the tween extension (I think that Arthuro is working on that).

To sum-up

I think we should only keep 1 zoom action.

"Relative" zoom parameters:

This will be a very simple extension that hides an exponential because it's not that trivial for people to do a constant zoom.

Elairyx7301 commented 2 years ago

Thanks for removing the "final fixes" tag. We should get to a point first before I continue the extension.

Exponential

Sorry for the misunderstanding, I know that the basic formula for zoom changes is exponential. This is why I've been using it in the expressions in almost all the past versions of that extension. I was trying to state that implementing TimeDelta() will not require another pow(x,y) method to do so.

Parameters

I think I got sidetracked a bit and described the scenario above with the absolute zoom. However, none of my mentioned aspects will be any different looking at the relative zoom instead of the absolute so this explanation still fully applies.

Camera Tweens

Indeed, the camera tween project has slipped off my radar and I don't mind leaving this method out but if I provide an extension for camera zoom, I don't want to tell the user that this extension isn't even complete. I would even say making the user use another action they might not be familiar with, the tweens, for it can be more complicated and less comfortable than just using lerp(CameraZoom("",0),0.8,0.1) in a regular camera zoom action - which would make the idea of the entire extension and the extension itself with it redundant.

Conclusion

I can totally understand you and the points you made and considering all that I also think only one "relative zoom" method is the best way out since that is a useful but, as you've already said, not the most trivial task so it will compensate for the other, seemingly, "missing" methods.

With this, I have changed my mind, I will take back the concerns I brought up about the incomplete extension and I do think this has cleared the path finish this extension.

Thank you for your time.

Elairyx7301 commented 2 years ago

Redundancies

To be honest, the more I think about the extension and what this extension has become the more I think it shouldn't be an extension but rather a feature request. since zooming a camera by a factor x every second sounds like a very niche application of camera zoom - especially because there is the camera tween being worked on. If the camera zoom tween works similar to the object related tweens (tween behavior) then this extension will not create anything new since the tween will ask for a duration of the tween either way. Therefore I don't think the expression for it alone would require a full extension for it.

@D8H What are your thoughts about this?

D8H commented 2 years ago

zooming a camera by a factor x every second sounds like a very niche application of camera zoom especially because there is the camera tween being worked on.

It could be used to do a smooth zoom out (or in) according to the character speed. It will probably be impossible to do with tweens because it must react to player inputs. It probably won't be used linearly, but it's easier to ease over something linear which this extension will provide.

In any case, I think it's still a good fit as an extension as it seems to be something:

Maybe, it could be interesting to try a zoom-out/zoom-in on a small platformer example and see if it can be done as easily without the extension.

Elairyx7301 commented 2 years ago

Hey @D8H, I've got the logic done and implemented but after some testing, I do not get the results I had expected according to the maths and logic behind it and would kindly ask you to take a look at the current status since I can imagine you are a bit better at stuff like this and have more experience and knowledge about the engine.

Current status

This version is not stable. This version is not complete. All descriptions, proper labeling and the like are missing and this is not the point of my ask. I primarily want it to work first. This is the easiest method I've found but I'm rather good at making everything thrice as complicated as it needs to be so if you just so happen to find a better method, I'd appreciate a hint towards it so I can try to implement it.

Approach explained

To double a value every second or time unit, starting from t_0 = 0, the function required would be 0.5 * 2^x. Taking the zoom factor (var: factor) and the possible delay (var: time) not as constants, I got the following function with factor ɛ ]0;∞[ and time ɛ ]-∞;∞[:

1/(factor^time) * factor^x

-> see visualization

Moreover, I implemented logic to make the current camera zoom have a common point with the (1/(factor^time)) * factor^x graph/function. For this, I used the -1.4429*ln(x) visible in the events. Since ln(x) is not available in the math library, I had to "simulate" it using log10(x)/log10(e) and, in lack of Euler's constant, only with e = 2.7182818285.


I have tried to manipulate the function in multiple ways to make the result more accurate to the wanted value but could not get it to satisfy me. Both expressions (original, manipulated) should be present in the events, one of them is disabled.

I'm sorry for asking so many questions but I really can't find my mistakes or ways to improve myself anymore. Please feel free to ping me here or on Discord if needed.

Visualization

geogebra.org/m/vrydeqvz

Files

CameraZoom v3.zip Extension.zip

Simplification of the expression used

//trigger once
__CameraZoom[GetArgumentAsString("Layer")].StartTime = TimeFromStart(); //needed to calculate delta time
__CameraZoom[GetArgumentAsString("Layer")].StartZoom = CameraZoom(GetArgumentAsString("Layer"),GetArgumentAsNumber("Camera"));
1/(factor^time) * factor^x

// next step =>
1/(factor^time) * factor^t //x = t (the actual time that passes in seconds)

// next step =>
1/(pow(factor, time)) * pow(factor, t)

// next step =>
1/(pow(factor, (-1.442 * ln(t)))) * pow(factor, t)

// next step =>
1/(pow(factor, (-1.442695 * ln(t)))) * pow(factor, (t-t0)) //t so time not absolute but relative from method call, t0 stored as variable once when method is called

// next step =>
1/(pow(factor, (-1.442695 * ln(t)))) * pow(factor, (TimeFromStart()-Variable(time0)))

// next step =>
1/(pow(GetArgumentAsNumber("ZoomFactor"), (-1.442695 * ln(t)))) * pow(GetArgumentAsNumber("ZoomFactor"), (TimeFromStart()-Variable(time0)))

// next step =>
1/(pow(GetArgumentAsNumber("ZoomFactor"), (-1.442695 * (log10(Variable(zoom0)) / log10(2.71828))))) * pow(GetArgumentAsNumber("ZoomFactor"), (TimeFromStart()-Variable(time0)))

// next step =>
(1/pow(GetArgumentAsNumber("ZoomFactor"),(-1.442695040889 * (log10(Variable(__CameraZoom[GetArgumentAsString("Layer")].StartZoom)) / log10(2.7182818285))))) *(pow(GetArgumentAsNumber("ZoomFactor"),(TimeFromStart()-Variable(__CameraZoom[GetArgumentAsString("Layer")].StartTime))))
D8H commented 2 years ago

I really don't understand what you are trying to achieve.

Why not just use the formula I gave the other day? zoom(t) = zoom(t - TimeDelta) * pow(factorSpeed, TimeDelta)

It worked well when I did a quick check. Did you get issues with it?

Elairyx7301 commented 2 years ago

Sorry, I'm afraid I also don't fully understand your formula.

This is the formula I have derived from yours. I am using a static factor (2), layer ("") and camera number (0) here for testing. The event with that new zoom value is called every frame.

camZoom = CameraZoom("",0) * pow(2, TimeDelta())
//camZoom = CameraZoom(Argument(layer),Argument(camera)) * pow(Argument(factor), TimeDelta())

From what I can tell, or from what I have interpreted, you say:       "Set current zoom to the zoom value the camera had TimeDelta() seconds (or one frame) ago and multiply it by       pow(factor, TimeDelta())"

The formula you gave me is rather confusing me because you have a zoom(t) method that is relative to itself, similar to f(x) = f(x - 1) and if that is valid I have no idea how to use it. Moreover, I think you wanted to write a formula that is not event-based so doesn't have a condition but since the event I am using is running every frame, zoom(t - TimeDelta) is rather the current zoom and zoom(t) is rather the new zoom value assigned this frame.

With this formula, I still get inaccurate results. This is the logic that I currently have for it: image

Here are the zoom values I get after every "cycle", starting from zoom level 1 (default), zoom factor is 2:

1.0, 1.9797, 3.9192, 7.7591, 15.3605

After four cycles, there is already a 4.16% deviation from the expected value. Is there something wrong with my setup or the formula?

D8H commented 2 years ago

After four cycles, there is already a 4.16% deviation from the expected value. Is there something wrong with my setup or the formula?

I'm sorry I can't help you with your formula because I don't understand it.

I modified your example to use the formula I suggested to be sure we're on the same page:

CameraZoom(GetArgumentAsString("Layer"), GetArgumentAsNumber("Camera")) * pow(GetArgumentAsNumber("ZoomSpeed"), TimeDelta())

When zooming in, the rouding errors are multiplied at every iteration so the zoom won't be exact but it seems accurate enough to me:

Time = 4.999926000000001 ->  Zoom = 31.998358669571058
Elairyx7301 commented 2 years ago

Sorry for the misunderstanding. I wasn't talking about my formula but about the one I said I'm currently using in the code a few lines above my question. I asked because I was confused by your formula a bit and wanted to make sure I have interpreted and "translated" it into GDevelop syntax correctly. Thank you for already adding descriptions and polishing the project even though I didn't expect you to ;p

After comparing our two versions, I've found that we were talking about an identical formula. However, even when adding my timer logic to your version and testing it, I still get the 4% deviation after four cycles. I assume it is my timer logic then since you have tested it and it worked for you.

I'm going to get the descriptions, labels etc. done in the next couple days and will hopefully post one of the last versions then.

Elairyx7301 commented 2 years ago

v3.0.1

Files

Extension.zip Project.zip

D8H commented 2 years ago
Elairyx7301 commented 2 years ago

v3.0.2

Extension.zip Project.zip


"Factor per second" is the unit of measurement. It can be given in the description but it must not be used everywhere. It can be called zoom speed.

Sorry, I don't understand what you mean by "it must not be used everywhere". I can only find Factor per second in the extension description and parameter description. However, if you are talking about the parameter label Zoom factor, I have to strongly disagree with you. Zoom speed does not indicate a unit or measurement in the slightest to me. A "factor" already implies a multiplication while a "speed" could be any unit for zooming.

The Layer parameter is missing an uppercase.

I do not have a clue of what you mean by that. In the parameter, the word "Layer" is spelled always with a capital "L", the event sentence purposely uses a capital "L" for consistency, I'm not using "Layer" in the scene nor in events. Could you please be more precise about what you mean and where you found the typo? Or, and also since you are already added to the authors' list, if it's just a typo etc., could you please fix it yourself? I think this will prevent redundant conversations and efforts through GitHub or Discord right away :) Thanks!


Changes

D8H commented 2 years ago

"Factor per second" is the unit of measurement. It can be given in the description but it must not be used everywhere. It can be called zoom speed.

Sorry, I don't understand what you mean by "it must not be used everywhere". I can only find Factor per second in the extension description and parameter description. However, if you are talking about the parameter label Zoom factor, I have to strongly disagree with you. Zoom speed does not indicate a unit or measurement in the slightest to me. A "factor" already implies a multiplication while a "speed" could be any unit for zooming.

For instance, in the platformer behavior, the action "Maximum falling speed" is describe like this "Change the maximum falling speed of an object (in pixel per second)". The term "speed" is concise and easy to understand. The description gives some details about it like the unit of measurement: "in pixel per second".

In my opinion, the full name must convey the general idea to allow users to find the action they need and the description bring the details that are needed to fully understand how to use the action.

To make an analogy, "Maximum pixel displacement per second when falling" is more precise than "Maximum falling speed", but it doesn't make it better for quickly find an action in a list.

The Layer parameter is missing an uppercase.

I do not have a clue of what you mean by that. In the parameter, the word "Layer" is spelled always with a capital "L", the event sentence purposely uses a capital "L" for consistency, I'm not using "Layer" in the scene nor in events. Could you please be more precise about what you mean and where you found the typo?

Yes, sorry about that I was switching between 2 versions and the typo was in the old one.

Or, and also since you are already added to the authors' list, if it's just a typo etc., could you please fix it yourself? I think this will prevent redundant conversations and efforts through GitHub or Discord right away :) Thanks!

I prefer not to modify the file because I would have to list all the changes I make either way so you can verify if you're ok with them and, if we don't share the same opinions, we would just revert each other work.

Elairyx7301 commented 2 years ago

I prefer not to modify the file because I would have to list all the changes I make either way so you can verify if you're ok with them and, if we don't share the same opinions, we would just revert each other work.

Oh yes, that makes sense. Alright, I didn't think about that :)

Changes

Files v3.0.3

Project.zip Extension.zip

D8H commented 2 years ago
Elairyx7301 commented 2 years ago

Thank you for your suggestions! I updated the most of those but commented on if and why I used or changed parts of it.


Name to "ZoomWithSpeed"

Change to "ZoomByFactor" for the already mentioned reason. The term "speed" can be anything while factor is a clear indicator on what a multiplication and therefore a zoom relative to the current one is happening. Moreover, I don't really see the huge importance of the method name inside the extension - especially if there is only one method at all in the first place.

Full name to "Change camera zoom with speed"

To me, "Zoom camera with speed" and "Change camera zoom with speed" say the exact same thing with the exception that from my intuition "change zoom" implies an absolute change as in "set to" and "zoom" represents an action that is in progress or is tied to a time span / duration rather than a time period. Not changed.

Description to "Change the camera zoom at a given speed (in a factor per second)."

I like the wording, changed to "Change the camera zoom at a given speed (in factor per second)".

Sentence to "Change the camera zoom at speed: _PARAM1_ (layer: _PARAM2_, camera: _PARAM3_)"

As mentioned, I think "change zoom" can be counterintuitive and "speed" is not as precise as "factor". Same set of reasons as above, not changed.

Zoom speed long description to "Zoom at a factor per second. 1: no change, 2: zoom in x2 every second, 0.5: zoom out x2 every second."

I'm stumbling over the "x2" a bit but I think that's just me. Changed to "Zoom by a factor per second. 2: zoom in x2 every second, 0.5: zoom out x2 every second". I removed the "1: no change" because if the user wants to use 1 as the zoom factor then I'm sure they can do without the extension :)

Files v3.0.4

Project.zip Extension.zip

I updated the comment, those are the newest files now

D8H commented 2 years ago

Name to "ZoomWithSpeed"

Change to "ZoomByFactor" for the already mentioned reason. The term "speed" can be anything while factor is a clear indicator on what a multiplication and therefore a zoom relative to the current one is happening. Moreover, I don't really see the huge importance of the method name inside the extension - especially if there is only one method at all in the first place.

It's important because it can't be changed and we don't know what will be added to the extension in the future. "Factor" alone sounds as if it's just a multiplication.

Full name to "Change camera zoom with speed"

To me, "Zoom camera with speed" and "Change camera zoom with speed" say the exact same thing with the exception that from my intuition "change zoom" implies an absolute change as in "set to" and "zoom" represents an action that is in progress or is tied to a time span / duration rather than a time period. Not changed.

I don't have a strong feeling about this, but I would say "Someone zoom on a bird with its camera" but not "Someone zoom its camera on a bird". "Zooming a camera" fells a bit weird to me, but if you think it's ok, it's fine.

As mentioned, I think "change zoom" can be counterintuitive and "speed" is not as precise as "factor". Same set of reasons as above, not changed.

"Speed" is a lot more precise than "factor". "Factor" only means multiplication which zoom already imply, so basically, "factor" give no information at all and is misleading because "factor" is not the same as "factor per second". Whereas with "speed", people will understand that they must keep calling it (we could make it explicit in the description) and that setting a constant in this parameter will result to a constant zoom speed.

Zoom speed long description to "Zoom at a factor per second. 1: no change, 2: zoom in x2 every second, 0.5: zoom out x2 every second."

I'm stumbling over the "x2" a bit but I think that's just me.

I used it to follow the wording of the "change camera zoom" action.

Changed to "Zoom by a factor per second. 2: zoom in x2 every second, 0.5: zoom out x2 every second". I removed the "1: no change" because if the user wants to use 1 as the zoom factor then I'm sure they can do without the extension :)

The value 1 is important to explain. It lets people know that values near 1 are slow zoom speeds and avoids someone to think the action doesn't do anything if they think the value 1 would mean something else.

Elairyx7301 commented 2 years ago

Alright, I have changed everything accordingly.

Changes

Files v3.0.5

Project.zip Extension.zip

D8H commented 2 years ago

Description

This extension allows to zoom the camera of a layer to a factor of its current value every second. Like that, when using the factor 2, the camera zoom will double every second. Using factors greater than 1 will zoom the camera in, a factor value below 1 will zoom the camera out. The zoom per second is independent from the FPS of the project.

Actions

  • Zoom by a factor every second

The extension description purpose is to let users know what they can do with the extension. It's not necessary to explain how to do it. The actions description already fills this purpose. If the extension were complex enough to need extra explanations, a wiki page would give them.

What about this instead? "This extension allows to zoom on a layer at a given speed. The zoom speed is configurable and allow a constant speed but also a variable one."

Zoom speed long description

Extension short descriptions and parameter long descriptions must end with a dot or the bot will get angry.

Elairyx7301 commented 2 years ago

Changes

Good catch! I thought I already changed it in the last version (I've also - and therefore mistakenly - added that to the changes list) but it seemed to have slipped by the latest save. Fixed now.

Files v3.0.6

Project.zip Extension.zip

D8H commented 2 years ago

Thank you, that seems good. I opened a PR with your exact version plus a dot.

Elairyx7301 commented 2 years ago

Sorry, I have no idea how that happened. I definitely added it and I thought I definitely saved after adding that dot. Edit: I did edit it but forgot to export the extension file as usual... Anyway, thanks :)

github-actions[bot] commented 2 years ago

Hi @Elairyx7301!

Thanks for your submission! Unfortunately, our automated test system found a few issues with your extension:

Please fix them, and edit the link in your original submission to a zip file with the fixed extension.

Thanks again for your hard work!

github-actions[bot] commented 2 years ago

Hi @Elairyx7301!

Thanks for your submission! Unfortunately, our automated test system found a few issues with your extension:

❌ 2 Errors found in extension 'CameraZoom':

  ⟶ ❌ (🔧) [Dots in sentences]: Field 'description' of the function 'ZoomWithSpeed' misses a dot at the end of the sentence!
  ⟶ ❌ [Extension name consistency]: Extension filename should be exactly the name of the extension (with .json extension). Please rename 'Extension.json' to 'CameraZoom.json'.

❌ 2 Errors found in extensions - please fix them before generating the registry.

Please fix them, and edit the link in your original submission to a zip file with the fixed extension.

Thanks again for your hard work!

Elairyx7301 commented 2 years ago

Done, original issue updated.

github-actions[bot] commented 2 years ago

Hi @Elairyx7301!

Thanks for your submission! Unfortunately, our automated test system found a few issues with your extension:

❌ 1 Error found in extension 'CameraZoom':

  ⟶ ❌ (🔧) [Dots in sentences]: Field 'description' of the function 'ZoomWithSpeed' misses a dot at the end of the sentence!

❌ 1 Error found in extensions - please fix it before generating the registry.

Please fix them, and edit the link in your original submission to a zip file with the fixed extension.

Thanks again for your hard work!

Elairyx7301 commented 2 years ago

Ok, I mean... would be done if I actually remembered to export the extension file 😅

github-actions[bot] commented 2 years ago

Hi @Elairyx7301! 👋 This submission has been moved to a PR as part of our submission pipeline. Please continue the submission process on this page. A few commands can be used there, use !update <Link to your zipped extension> to update the extension in the PR, and !merge to merge changes from the main branch into your PR. Thanks again for your submission!

github-actions[bot] commented 2 years ago

Hi @Elairyx7301! 👋 This submission has been moved to a PR as part of our submission pipeline. Please continue the submission process on this page. A few commands can be used there, use !update <Link to your zipped extension> to update the extension in the PR, and !merge to merge changes from the main branch into your PR. Thanks again for your submission!