-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow the use of Timer as a Cooldown / Create a Cooldown struct #1127
Comments
This is an interesting proposal. I think the To make sure I'm understanding you correctly, the core issues are:
We might be able to get away with 1 through some specialty methods. The latter seems like it might be a better fit for a thin wrapper around Timer, either in the individual game / crate or within Bevy itself. I'm a bit worried about redundancy if we put it in Bevy, but making it a thin wrapper would reduce the maintenance burden substantially. On To get rid of the struct HelloTimer(Timer);
// These Deref impls are optional sugar to make using these timers more pleasant.
// Rather than having to use `my_hello_timer.0` every time we want to use one of these objects
// we can just call `my_hello_timer` directly
impl Deref for HelloTimer{
type Target = Timer;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for HelloTimer{
fn deref_mut(&mut self) -> &mut Timer {
&mut self.0
}
} Not thrilled with the amount of space that takes up; maybe a simple derive trait or proc macro is called for? |
The
Yes, that is correct, there are other usecases like auto-fire for weapons and stuff like that (cooldowns for spells).
Yeah, this is right, although it's a bit more subtle than simply inverted booleans because when a cooldown is ticking it's not available, and the same goes for the
My take on that is that
I'm not familiar with those features, but I think it will be clearer once the
I don't know if that's part of my issue, but I agree that the NewType pattern for this is not very adequate. Maybe enforce that the timer is used with a type like |
Thanks for the explanations; I think I'm on board with making Cooldowns a standard bit of kit. I really like the I think this calls for a new issue (or PR) to overhaul the Timer-related API at this point :) |
I tried there are two issues: |
Oh woaw that's quite a lot of change I wasn't expecting as much!
Yes, that is indeed a hassle. Are there still problems with the work around you propose ?
Can you elaborate a bit more on why this is a problem? User defined timers will be components, resources, or locals in any cases, just like other user defined structs? Regarding the initial |
This pull request is following the discussion on the issue #1127. Additionally, it integrates the change proposed by #1112. The list of change of this pull request: * 💥 Change `Timer` to `Timer<T>` in order to make specialization very explicit to the user, while removing the boilerplated NewType pattern for Timers. This is a breaking change * ✨ Add `Timer::times_finished` method that counts the number of wraps for repeating timers. * ♻️ Refactored `Timer` * 🐛 Fix a bug where 2 successive calls to `Timer::tick` which makes a repeating timer to finish makes `Timer::just_finished` to return `false` where it should return `true`. Minimal failing example: ```rust use bevy::prelude::*; let mut timer: Timer<()> = Timer::from_seconds(1.0, true); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); // <- This fails where it should not ``` * 📚 Add extensive documentation for Timer with doc examples. * ✨ Add `Cooldown` and `Stopwatch` structs similar to `Timer` with extensive doc and tests. Even if the type specialization is not retained for bevy, the doc, bugfix and added method are worth salvaging 😅. This is my first PR for bevy, please be kind to me ❤️ . Co-authored-by: Carter Anderson <[email protected]>
This pull request is following the discussion on the issue #1127. Additionally, it integrates the change proposed by #1112. The list of change of this pull request: * ✨ Add `Timer::times_finished` method that counts the number of wraps for repeating timers. * ♻️ Refactored `Timer` * 🐛 Fix a bug where 2 successive calls to `Timer::tick` which makes a repeating timer to finish makes `Timer::just_finished` to return `false` where it should return `true`. Minimal failing example: ```rust use bevy::prelude::*; let mut timer: Timer<()> = Timer::from_seconds(1.0, true); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); // <- This fails where it should not ``` * 📚 Add extensive documentation for Timer with doc examples. * ✨ Add a `Stopwatch` struct similar to `Timer` with extensive doc and tests. Even if the type specialization is not retained for bevy, the doc, bugfix and added method are worth salvaging 😅. This is my first PR for bevy, please be kind to me ❤️ . Co-authored-by: Carter Anderson <[email protected]>
This pull request is following the discussion on the issue #1127. Additionally, it integrates the change proposed by #1112. The list of change of this pull request: * ✨ Add `Timer::times_finished` method that counts the number of wraps for repeating timers. * ♻️ Refactored `Timer` * 🐛 Fix a bug where 2 successive calls to `Timer::tick` which makes a repeating timer to finish makes `Timer::just_finished` to return `false` where it should return `true`. Minimal failing example: ```rust use bevy::prelude::*; let mut timer: Timer<()> = Timer::from_seconds(1.0, true); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); // <- This fails where it should not ``` * 📚 Add extensive documentation for Timer with doc examples. * ✨ Add a `Stopwatch` struct similar to `Timer` with extensive doc and tests. Even if the type specialization is not retained for bevy, the doc, bugfix and added method are worth salvaging 😅. This is my first PR for bevy, please be kind to me ❤️ . Co-authored-by: Carter Anderson <[email protected]>
We should probably close this issue since it was merged to bevy 0.5 |
What problem does this solve or what need does it fill?
A Cooldown is like a timer except it's
available
when constructed and areset
make it available again.The
Timer
struct currently can't be used to make a "cooldown" behavior because of the following minor differences between the two:Timer::finished() == false
Cooldown::available() == true
Timer::finished() == false
Cooldown::available() == true
N.A.
Cooldown::available()
goes fromtrue
tofalse
and the cooldown start ticking (only for non looping Cooldowns).I found the need for this behavior when implementing my sprite sheet animation system for my game. I need that a change of animation (from Idle to Attack for example) occur directly and not on the next animation frame in order to increase responsiveness (I'm sure there are other needs for this particular behavior).
Describe the solution would you like?
Because of the similarity of behavior of both things, my idea would be to have them share part of the code. But it could also be a new struct with a very similar API.
A cooldown could be made with a timer by doing the following:
However, implementing it this way is fragile because it doesn't support looping cooldown, and is a bit messy to use.
Describe the alternative(s) you've considered?
The more I think of it, the more I think that having a different struct for this job is more appropriate for the reason that it's not a complicated behavior and also that the ticking mechanism, although similar, is quite different.
Maybe the ticking, pausing, elapsed times could be factored out in a
Chronometer
struct that both those two things could use?Additional context
An example of what a
Cooldown
struct could look like:I'm sorry if this is a bit messy, It's my first issue. I love your work on bevy, I think it's really great! I would be happy to help integrate this feature in bevy if you find it belongs there!
The text was updated successfully, but these errors were encountered: