Update 'Analog Clock'

sigonasr2 2025-04-08 14:32:34 -05:00
parent 486d2f29e5
commit 0e4dea33d2

@ -486,3 +486,51 @@ It all looks like this:
<a href="https://pgetinker.com/s/SnIkSOJ7Vk" title="Click to try it out!" target="_blank">[***Try it out!***]</a> <a href="https://pgetinker.com/s/SnIkSOJ7Vk" title="Click to try it out!" target="_blank">[***Try it out!***]</a>
<a href="https://pgetinker.com/s/SnIkSOJ7Vk" title="Click to try it out!" target="_blank"><img src="https://pit.pgetinker.com/S2ySVCFsMKgw.png" width="256" height="240"></a> <a href="https://pgetinker.com/s/SnIkSOJ7Vk" title="Click to try it out!" target="_blank"><img src="https://pit.pgetinker.com/S2ySVCFsMKgw.png" width="256" height="240"></a>
## "Ticking" Jump Back Motion
When the second hand jumps forward, it has a slight jump back as it locks into place. It's very subtle but also a feature in analog clocks that I like. Let's try to recreate that subtle detail.
Start by adding a new variable to track the amount of time it takes before the second hand "jumps back". We'll make it 0.02 seconds for now (very subtle). We also need a variable tracking what the amount of seconds that have passed was the previous frame. If it ever differs, we set the `secondHandBounceTimer` to `0.02` and it starts decreasing by `GetElapsedTime()` (the amount of time in seconds that have passed for this rendering frame).
One way we would be able to trigger the "tick back" motion is by modifying the `DrawHand()` lambda inside `DrawClockHands()` to have a float parameter passed in with an "additional rotation" amount.
First update the `DrawHand()` lambda with the new parameter and angle offset:
```cpp
const auto DrawHand=[&](const float handLength,const float secondsPerRevolution,const olc::Pixel col,const float angleOffset=0.f){
using namespace std::numbers;
const float angle{float(2*pi*fmod(totalTime,secondsPerRevolution)/secondsPerRevolution+angleOffset)};
olc::vf2d handVec{handLength,float(angle-pi/2)};
DrawLine(GetScreenSize()/2,GetScreenSize()/2+handVec.cart(),col);
};
```
Add two new variables into the game class:
```cpp
public:
bool OnUserCreate() override
{
return true;
}
float secondHandBounceTimer{0.f};
size_t lastSecond{};
```
Update the last second value and the bounce timer if it changes.
```cpp
if(lastSecond!=localTime->tm_sec){
secondHandBounceTimer=0.02f;
lastSecond=localTime->tm_sec;
}
```
In `OnUserUpdate()` we have to tick down the bounce timer. We use `std::max` as it's equivalent to `if(secondHandBounceTimer>0)secondHandBounceTimer-=fElapsedTime; secondHandBounceTimer=std::max(secondHandBounceTimer,0.f);`
```cpp
secondHandBounceTimer=std::max(secondHandBounceTimer-fElapsedTime,0.f);
```
Finally, apply the bounce timer to the `DrawHand()` call for the second hand.
```cpp
DrawHand(85,60,olc::RED,secondHandBounceTimer);
```
Screenshots don't do it justice, but look at the results for yourself and it is a pretty convincing behavior!
<a href="https://pgetinker.com/s/k2GF-BTk2tQ" title="Click to try it out!" target="_blank">[***Try it out!***]</a>
<a href="https://pgetinker.com/s/k2GF-BTk2tQ" title="Click to try it out!" target="_blank"><img src="https://pit.pgetinker.com/W4tqHfCm4TXo.png" width="256" height="240"></a>